Wikikamus
mswiktionary
https://ms.wiktionary.org/wiki/Wikikamus:Laman_Utama
MediaWiki 1.47.0-wmf.3
case-sensitive
Media
Khas
Perbincangan
Pengguna
Perbincangan pengguna
Wikikamus
Perbincangan Wikikamus
Fail
Perbincangan fail
MediaWiki
Perbincangan MediaWiki
Templat
Perbincangan templat
Bantuan
Perbincangan bantuan
Kategori
Perbincangan kategori
Lampiran
Perbincangan lampiran
Rima
Perbincangan rima
Tesaurus
Perbincangan tesaurus
Indeks
Perbincangan indeks
Petikan
Perbincangan petikan
Rekonstruksi
Perbincangan rekonstruksi
Padanan isyarat
Perbincangan padanan isyarat
Konkordans
Perbincangan konkordans
TimedText
TimedText talk
Modul
Perbincangan modul
Acara
Perbincangan acara
harimau
0
4494
344387
239671
2026-05-26T03:38:53Z
Hakimi97
2668
/* Terjemahan */
344387
wikitext
text/x-wiki
{{wikipedia|Harimau}}
[[Fail:Panthera tigris tigris.jpg|thumb|Harimau belang]]
== Bahasa Melayu ==
===Takrifan===
{{ms-kn}}
# sejenis haiwan [[mamalia]] [[maging]] besar dalam famili [[kucing]] yang berasal dari Asia, khususnya harimau belang, ''Panthera tigris''.
====Kata terbitan====
* mengharimaui: memarahi dengan dahsyat.
===Etimologi===
<!--Daripada bahasa ?-->
===Sebutan===
{{dewan|ha|ri|mau}}
===Tulisan Jawi===
{{ARchar|هريماو}}
===Terjemahan===
{{ter-atas|Haiwan mamalia ''Panthera tigris''}}{{multitrans|data=
* Abkhaz: {{tt|ab|атигр}}
* Aceh: {{tt|ace|rimuëng}}
* Afrikaans: {{tt+|af|tier}}
* Ahom: {{tt|aho|𑜏𑜢𑜤𑜰𑜫}}, {{tt|aho|𑜏𑜢𑜤𑜈𑜫}}
* Aiton: {{tt|aio|ꩬိုဝ်}}
* Alabama: {{tt|akz|kowibasbaki}}, {{tt|akz|kowiɬahkachi}}
* Albania: {{tt+|sq|tigër|m}}
* Altai:
*: Altai Utara: {{t|atv|марс}}, {{t|atv|парс}}
*: Altai Selatan: {{t|alt|барс}}
* Amhara: {{tt|am|ነብር}}
* Amuzgo:
*: Amuzgo Guerrero: {{tt|amu|kítziaⁿ}}
* Angami: {{tt|njm|tekhu}}
* Ao: {{t|njo|keyi}} {{q|Chungli}}
* Aoheng: {{tt|pni|sengiru}}, {{tt|pni|sengiro}}, {{tt|pni|singiro}}
* Arab: {{tt+|ar|نِمْر|m}}, {{tt+|ar|بَبْر|m}}
*: Arab Mesir: {{tt|arz|نمر|m|tr=nimr}}
*: Arab Hijaz: {{t|acw|نمر|m|tr=nimir}}
* Aram:
*: Neo-Aram Assyria: {{t-needed|aii}}
*: Suryani Klasik: {{tt|syc|ܛܝܓܪܝܣ|f|tr=ṭīḡrīs}}, {{tt|syc|ܒܒܪܐ|m|ts=bbrʾ}}
*: Aram Babylon Ibrani: {{tt|arc|טִיגְרִיס|m|tr=ṭîḡrîs}}
* Archi: {{tt|aqc|цӏиркъ}}
* Armenia: {{tt+|hy|վագր}}
* Assam: {{tt|as|ঢেঁকীয়াপতীয়া বাঘ}}, {{tt|as|বাঘ}} {{q|hypernym}}
* Asturias: {{tt+|ast|tigre|m}}
* Atayal: {{t|tay|zkliʼ}}
* Avar: {{tt|av|цӏиркъ}}
* Awadhi: {{tt|awa|बाघ|m}}
* Azeri: {{tt+|az|pələng}}
* Melayu Baba: {{tt|mbf|arimo}}
* Bahnar: {{tt|bdq|kla}}
* Bali: {{tt|ban|macan}}
* Baluchi: {{tt|bal|مزار|tr=mazár}}
* Bashkir: {{tt|ba|юлбарыҫ}}
* Basque: {{tt+|eu|tigre}}
* Batak:
*: Batak Mandailing: {{tt+|btm|babiat}}
*: Batak Toba: {{tt|bbc|babiat}}, {{tt|bbc|babiak}}, {{tt|bbc|ompung}}, {{tt|bbc|ompungi}}
* Batek: {{tt|btq|yah}}, {{tt|btq|ayok}}, {{tt|btq|ayõng}}, {{tt|btq|pangan}}, {{tt|btq|ãp}}, {{tt|btq|iyah}}, {{tt|btq|bek}}, {{tt|btq|gayi}}
* Belarus: {{tt|be|тыгр|m}}, {{tt|be|ты́гра|f}} {{qualifier|colloquial}}
* Bengali: {{tt+|bn|বাঘ}}
* Berawan: {{tt|lod|upo}}
* Besisi: {{tt|mhe|a'a}}, {{tt|mhe|a'ak}}, {{tt|mhe|tuéh}}, {{tt|mhe|malap}}
* Bhojpuri: {{t|bho|बाघ}}
* Bidayuh:
*: Bidayuh Bau: {{tt|sne|rimoung}}
*: Bidayuh Bukar-Sadung: {{tt|sdo|limo}}
* Bouyei: {{tt|pcc|gugt}}, {{tt|pcc|duezgugt}}
* Breton: {{tt+|br|tigr|m}}
* Bugis: {{tt|bug|macang}}
* Bulgaria: {{tt+|bg|ти́гър|m}}
* Bundeli: {{tt|bns|नाहर|m}}
* Burma: {{tt+|my|ကျား}}
* Burusu: {{tt|bqr|mintik inon}}
* Catalonia: {{tt+|ca|tigre|m}}
* Cebuano: {{tt|ceb|tigre}}
* Tamazight Atlas Tengah: {{tt|tzm|ⴰⵖⵉⵍⴰⵙ|m}}
* Cham:
*: Cham Timur: {{tt|cjm|rimông}}, {{tt|cjm|ramông}}
*: Cham Barat: {{tt|cja|ramông}}
* Chechen: {{tt|ce|цӏоькъалом}}
* Cherokee: {{tt|chr|ᏢᏓᏥ ᏧᎶᎸᏗ}}
* Chewong: {{tt|cwg|kle}}, {{tt|btq|keli}}
* Cina:
*: Kantonis: {{tt|yue|老虎|tr=lou5 fu2}}
*: Dungan: {{tt|dng|лохў}}, {{tt|dng|хў}}
*: Min Timur: {{tt|cdo|老虎|tr=lâu-hū}}
*: Gan: {{tt|gan|老虎|tr=lau3 'fu3}}
*: Hakka: {{tt|hak|老虎|tr=lo-fú}}
*: Hokkien: {{tt+|nan-hbl|虎|tr=hó͘}}
*: Jin: {{tt|cjy|老虎|tr=lau2 hu2}}
*: Mandarin: {{tt+|cmn|老虎|tr=lǎohǔ}}, {{tt+|cmn|虎|tr=hǔ}} {{q|klasik atau dalam bentuk kata majmuk}}
*: Wu: {{tt|wuu|老虎}}
*: Xiang: {{tt|hsn|老虎|tr=lau3 fu}}
* Chru: {{tt|cje|rơmòg}}
* Circassia:
*: Circassia Timur: {{tt+|kbd|къаплъэн}}, {{tt|kbd|хьэщомыщ}}
*: Circassia Barat: {{tt|ady|къаплъэн}}, {{tt|ady|къэплъан}}
* Koptik: {{tt|cop|ϫⲓⲕⲣⲓⲥ|m}}
* Cornwall: {{tt|kw|tiger|m}}, {{tt+|kw|tygra}}
* Corsica: {{tt+|co|tigru|m}}
* Cree:
*: Montagnais: {{tt|moe|minashkuau-minush}}
* Czech: {{tt+|cs|tygr|m}}
* Denmark: {{tt+|da|tiger|c}}
* Dhivehi: {{tt|dv|މިނިކާވަގަ}}
* Dongxiang: {{tt|sce|basi}}
* Dusun:
*: Kadazandusun: {{tt|dtp|rimau}}
* Dutch: {{tt+|nl|tijger|m}}
* Dzongkha: {{tt|dz|སྟག}}
* Embaloh: {{tt|emb|baro}}
* Enggano: {{tt|eno|nimau}}
* Erzya: {{tt|myv|бабри}}
* Esperanto: {{tt+|eo|tigro}}
* Estonia: {{tt|et|tiiger}}
* Faroe: {{tt|fo|tikari|m}}
* Finland: {{tt+|fi|tiikeri}}
* Perancis: {{tt+|fr|tigre|m}}, {{tt+|fr|tigresse|f}}
* Frisia:
*: Frisia Barat: {{tt+|fy|tiger|c}}
* Galicia: {{tt+|gl|tigre|m}}, {{tt|gl|tigresa|f}}
* Gayo: {{tt|gay|kule}}
* Georgia: {{tt+|ka|ვეფხვი}}
* Jerman: {{tt+|de|Tiger|m}}, {{tt+|de|Tigerin|f}}, {{tt|de|Tigermännchen|n}} {{qualifier|male}}, {{tt|de|Tigerweibchen|n}} {{qualifier|female}}
*: Jerman Tanah Tinggi Pertengahan: {{tt|gmh|tigertier|n}}
*: Jerman Tanah Tinggi Kuno: {{tt|goh|tigirtior|n}}, {{tt|goh|tigritior|n}}
* Gondi: {{tt|gon|బుర్కల్|tr=burkal}}
* Gong: {{tt|ugo|เดือ}}
* Yunani: {{tt+|el|τίγρη|m|f}}, {{tt+|el|τίγρης|m}}
*: Yunani Kuno: {{tt|grc|τίγρις|m|f}}
* Greenland: {{tt+|kl|tiigeri}}
* Guarani:
*: Guarani Paraguay: {{tt-check|gug|jaguarete}}
* Gujarati: {{tt+|gu|વાઘ|m}}
* Kreol Haiti: {{tt|ht|tig}}
* Haroi: {{tt|hro|lĕmung}}
* Ibrani: {{tt+|he|טִיגְרִיס|m|tr=tígris}}
* Hindi: {{tt+|hi|बाघ|m}}, {{tt+|hi|व्याघ्र|m}}, {{tt+|hi|नाहर|m}}, {{tt+|hi|केहर|m}}
* Hmong:
*: A-Hmao: {{t|hmd|𖼯𖽙𖾑}}
*: Hmong Putih: {{tt|mww|tsov}}
* Hungary: {{tt+|hu|tigris}}
* Iban: {{tt|iba|remaung}}
* Iceland: {{tt+|is|tígur|m}}
* Ida'an: {{tt|dbj|kakkang}} (young)
* Ido: {{tt+|io|tigro}}
* Igbo: {{t|ig|agụ}}
* Indonesia: {{tt+|id|harimau}}
* Ingrian: {{tt|izh|tigra}}
* Ingush: {{tt|inh|цӀокъ}}
* Interlingua: {{tt|ia|tigre}}
* Irish: {{tt+|ga|tíogar|m}}
* Itali: {{tt+|it|tigre|f}}
* Jah Hut: {{tt|jah|kelaq}}
* Jepun: {{tt+|ja|虎|tr=とら, tora}}
* Jarai: {{tt|jra|rờmōng}}
* Jawa: {{tt+|jv|macan}}, {{tt|jv|gémbong}} (ngoko), {{tt+|jv|gogor}} (young), {{tt|jv|sima}} (krama), {{tt+|jv|wiyagra}}, {{tt+|jv|sardula}}, {{tt+|jv|bowong}}
*: Jawa Kuno: {{tt|kaw|macan}}, {{t|kaw|bowoṅ}}, {{t|kaw|harimoṅ}}, {{t|kaw|hariwyāghra}}, {{t|kaw|moṅ}}, {{t|kaw|mṛgādhipa}}, {{t|kaw|mṛganātha}}, {{t|kaw|mṛgapati}}, {{t|kaw|mṛgaprabhu}}, {{t|kaw|mṛgarāja}}, {{t|kaw|mṛgendra}}, {{t|kaw|puhun}}, {{t|kaw|samoṅ}}, {{t|kaw|śārdūla}}, {{t|kaw|śārdūlākṛti}}, {{t|kaw|wasari}}, {{t|kaw|wasarya}}, {{t|kaw|wyāghra}}
* Jehai: {{tt|jhi|ap}}, {{tt|jhi|ju'ok}}, {{tt|jhi|baling}}, {{tt|jhi|putew}}
* Kalmyk: {{tt|xal|ирвск}}
* Kannada: {{tt+|kn|ಹುಲಿ}}
* Karachay-Balkar: {{tt|krc|къаплан|tr=qaplan}}
* Karen:
*: Karen Pa'o: {{tt|blk|ကေ}}
* Kazakh: {{tt|kk|жолбарыс}}
* Kelabit: {{tt|kzi|balang}}
* Kensiu: {{tt|kns|émet}}, {{tt|kns|tayok}}, {{tt|kns|ong}}
* Kerinci: {{tt|kvr|imaw}}
* Khalaj: {{t|klj|bəbr}}, {{t|klj|palang}}
* Khamti: {{t-needed|kht}}
* Khasi: {{tt|kha|khla}}
* Khmer: {{tt+|km|ខ្លា}}, {{tt+|km|ខ្លាធំ}}
* Korea: {{tt+|ko|호랑이}}, {{tt+|ko|범}}
*: Korea Pertengahan: {{tt|okm|범〯}}
* Kristang: {{tt|mcm|trigi}}
* Kubu: {{tt|kvb|mer'ego}}, {{tt|kvb|natong hidup}}
* Kumyk: {{tt|kum|къаплан|tr=qaplan}}
* Kurdi:
*: Kurdi Tengah: {{tt|ckb|بەور}}
*: Kurdi Utara: {{tt+|kmr|piling}}
* Kyrgyz: {{tt+|ky|жолборс}}
* Lampung Api: {{tt|ljp|kumbok}}, {{tt|ljp|lemawong}}, {{tt|ljp|lemameng}}, {{tt|ljp|waw}}, {{tt|ljp|jin}}
* Lao: {{tt+|lo|ເສືອ}}
* Latin: {{tt+|la|tīgris|m|f}}
* Latvia: {{tt|lv|tīģeris|m}}
* Lawangan: {{tt|lbx|timang}}, {{tt|lbx|timaang}}
* Lezgi: {{tt|lez|пеленг}}
* Liguria: {{tt|lij|tîgre|f}}
* Limburg: {{tt+|li|tieger|m}}
* Lisu: {{tt|lis|ꓡꓽ}}
* Lithuania: {{tt+|lt|tigras|m}}
* Jerman Tanah Rendah: {{tt|nds|Tieger|m}}
* Lü: {{tt|khb|ᦵᦉᦲ}}
* Lutuv: {{t|clt|cakyi}}, {{t|clt|kyipuv}}
* Luxembourg: {{tt|lb|Tiger|m}}
* Makedonia: {{tt|mk|тигар|m}}
* Malagasy: {{tt+|mg|trimo}}
* Melayu:
*: Melayu Brunei: {{tt|kxd|haimau}} {{q|Kedayan}}
*: Melayu Barisan: {{tt|pse|setue}}, {{tt|pse|ne'ngau}} {{q|Besemah}}
*: Melayu Barisan: {{tt|pse|setuau}}, {{tt|pse|setuo}} {{q|Serawai}}
*: Melayu Kutai Kota Bangun: {{tt|mqg|remaong}}
* Malayalam: {{tt+|ml|കടുവ}}
* Malta: {{tt|mt|tigra|f}}
* Manchu: {{tt|mnc|ᡨᠠᠰᡥᠠ}}, {{tt|mnc|ᠮᡠᡥᠠᠨ}} {{qualifier|male}}, {{tt|mnc|ᠪᡳᡵᡝᠨ}} {{qualifier|female}}, {{tt|mnc|ᡨᠠᡵᡶᡠ}}
* Manx: {{tt|gv|çheegyr|m}}, {{tt|gv|teigyr|m}}
* Māori: {{tt|mi|taika}}
* Mapudungun: {{tt|arn|nahuel}}
* Marathi: {{tt|mr|वाघ|m}}
* Mazanderani: {{tt|mzn|پلنگ|tr=paleng}}, {{tt|mzn|ببر|tr=baber }}, {{tt|mzn|دورگ|tr=dorag}}
* Melanau:
*: Melanau Tengah: {{tt|mel|rimau}}, {{tt|mel|rimau baleng}}
* Inggeris Pertengahan: {{tt|enm|tygre}}
* Minangkabau: {{tt+|min|inyiak}}
* Mingrelia: {{tt|xmf|ჸილო}}
* Minriq: {{tt|mnq|lodap}}, {{tt|mnq|ap}}
* Mohawk: {{t|moh|takoʼskó꞉wa}}
* Mon: {{tt+|mnw|ကၠ|tr=klaˀ}}
* Mongol:
*: Sirilik: {{tt+|mn|бар}}
*: tulisan Mongol: {{tt|mn|ᠪᠠᠷᠰ}}
* Muong: {{tt|mtq|khảl}}
* Murut:
*: Murut Serudung: {{tt|srk|takinon}}
* Naga:
*: Naga Khiamniungan: {{t|kix|khāu}}
* Nanai: {{tt|gld|амбан}}
* Navajo: {{tt|nv|náshdóítsoh noodǫ́zígíí}}
* Nepal: {{tt+|ne|बाघ}}
* Ngaju: {{tt|nij|haramaung}}
* Nivkh: {{tt|niv|ат}}, {{tt|niv|иғлуладь}}
* Nogai: {{tt|nog|йолбарыс}}
* Norwey:
*: Bokmål: {{tt+|nb|tiger|m}}
*: Nynorsk: {{tt+|nn|tiger|m}}
* Nuosu: {{tt|ii|ꆿ}}
* Occitania: {{tt+|oc|tigre|m}}
* Odia: {{tt+|or|ବାଘ}}
* Slav Gereja Kuno: {{tt|cu|тигръ|m}}
* Inggeris Kuno: {{tt|ang|tiger|m}}
* Oromo: {{tt|om|qeerramsa}}
* Oroqen: {{tt|orh|ʊta꞉tʃi}}
* Ossetia: {{tt|os|тигр}}
* Pacoh: {{tt|pac|cula}}
* Pali:
*: Bengal: {{tt|pi|ব্যগ্ঘ|m}}
*: Burma: {{tt|pi|ဗျဂ္ဃ|m}}
*: Devanagari: {{tt|pi|ब्यग्घ|m}}
*: Khmer: {{tt|pi|ព្យគ្ឃ|m}}
*: Latin: {{tt|pi|byaggha|m}}
*: Sinhala: {{tt|pi|බ්යග්ඝ|m}}
*: Tai Tham: {{tt|pi|ᨻ᩠ᨿᨣ᩠ᨥ|m}}
*: Thai: {{tt|pi|พฺยคฺฆ|m}}
* Rusyn Pannonia: {{t|rsk|тиґриш|m}}, {{t|rsk|тиґер|m}}
* Pashto: {{tt|ps|پړانګ|m|tr=pṛāng}}
* Pawnee: {{tt|paw|pakstítkukiic}}
* Penan:
*: Penan Timur: {{tt|pez|piad}}
*: Penan Barat: {{tt|pne|biat}}
* Parsi:
*: Dari: {{tt|prs|بَبْر}}
*: Parsi Iran: {{tt|fa-ira|بَبْر}}
* Phake: {{t-needed|phk}}
* Plautdietsch: {{tt|pdt|Tieja|m}}
* Poland: {{tt+|pl|tygrys|m-an}}
* Portugis: {{tt+|pt|tigre|m}}
* Prakrit:
*: Prakrit Ardhamagadhi: {{tt|pra-ard|𑀯𑀕𑁆𑀖|m}}
*: Prakrit Maharastri: {{tt|pra-mah|𑀯𑀕𑁆𑀖|m}}
*: Prakrit Sauraseni: {{tt|pra-sau|𑀯𑀕𑁆𑀖|m}}
* Tubu Punan: {{tt|puj|vi'at}}, {{tt|puj|fi'at}}
* Punjabi:
*: Gurmukhi: {{tt+|pa|ਸ਼ੇਰ|m}}, {{tt|pa|ਬਾਘ|m}}
*: Punjabi Barat: {{tt+|pnb|شیر|m}}, {{tt|pnb|باگھ|m}}
* Quechua: {{tt|qu|uthurunku}}
* Rade: {{tt|rad|êmông}}
* Rejang: {{tt|rej|imêu}}
* Roglai:
*: Roglai Utara: {{tt|rog|lumõng}}
* Rohingya: {{tt|rhg|bag}}
* Romagnol: {{tt|rgn|tigra|f}}
* Romania: {{tt+|ro|tigru|m}}
* Rungus: {{tt|drg|orimau}}
* Rusia: {{tt+|ru|тигр|m-an}}
* Saek: {{tt|skb|กู̄ก}}
* Salako: {{tt|knx|rimong}}
* Sanskrit: {{tt+|sa|व्याघ्र|m}}
* Santali: {{tt+|sat|ᱛᱟᱹᱨᱩᱵ}}
* Saurashtra: {{tt|saz|ꢮꢵꢔ꣄}}
* Scots: {{tt|sco|teeger}}
* Semai: {{tt|sea|atañ}}, {{tt|sea|kaap}}, {{tt|sea|berenggas}}, {{tt|sea|raak}}, {{tt|sea|mameek}}, {{tt|sea|mergas}}, {{tt|sea|bergas}}, {{tt|sea|nyuuq}}, {{tt|sea|keek}}, {{tt|sea|bagòr}}, {{tt|sea|kaam}}, {{tt|sea|rerok}}
* Semaq Beri: {{tt|szc|gayit}}
* Semnam: {{tt|ssm|kmuuc}}
* Serbo-Croatia:
*: Sirilik: {{tt|sh|тигар|m}}
*: Latin: {{tt+|sh|tigar|m}}
* Shan: {{tt+|shn|သိူဝ်}}
* Sian: {{tt|spg|piyat}}
* Siang: {{tt|sya|hôrômaung}}
* Sicily: {{tt+|scn|tigri|f}}, {{tt|scn|trighi|f}}
* Sindhi: {{tt|sd|واگھُ|m|tr=vāghu}}
* Sinhala: {{tt+|si|කොටියා}}
* Slovak: {{tt+|sk|tiger|m}}
* Slovene: {{tt+|sl|tiger|m}}
* Somali: {{tt+|so|shabeel}}
* Sorbia:
*: Sorbia Hilir: {{tt|dsb|tiger|m}}
*: Sorbia Hulu: {{tt|hsb|tiger|m}}
* Sepanyol: {{tt+|es|tigre|m}}
* Sunda: {{tt|su|lodaya}}, {{tt+|su|maung}}, {{tt+|su|aom}} (young), {{tt|su|rimau}}
* Swahili: {{tt|sw|chui milia}}, {{tt+|sw|simba marara|c9|c10}}
* Sweden: {{tt+|sv|tiger|c}}
* Sylheti: {{tt|syl|ꠛꠣꠊ}}
* Tabasaran: {{tt|tab|пеленг}}
* Tagalog: {{tt+|tl|tigre}}
* Tai Dam: {{tt|blt|ꪹꪎ}}
* Tai Nüa: {{tt|tdd|ᥔᥫᥴ}}
* Tajik: {{tt+|tg|бабр}}
* Tamil: {{tt+|ta|புலி}}
* Tarao: {{tt|tro|yokpi}}
* Tatar: {{tt+|tt|юлбарыс}}
* Telugu: {{tt+|te|పులి|?}}, {{tt+|te|వ్యాఘ్రము|m}}
* Temiar: {{tt|tea|mamuh}}, {{tt|tea|merges}}, {{tt|tea|mamuug}}, {{tt|tea|aab}}
* Temoq: {{tt|tmo|barangmoh}}, {{tt|tmo|daying}}, {{tt|tmo|mĕ'ong}}, {{tt|tmo|tĕhoqpolan}}, {{tt|tmo|pĕn-yow}}
* Ten'edn: {{tt|tnz|o'}}
* Thai: {{tt+|th|เสือ}}, {{tt+|th|โคร่ง|alt=เสือโคร่ง|tr=sʉ̌ʉa-krôong}}
* Tibet: {{tt|bo|སྟག}}
* Tigrinya: {{tt|ti|ነብሪ}}
* Tobilung: {{tt|tgb|mondou}}, {{tt|tgb|tatanansad}}
* Tocharia B: {{tt|txb|mewiyo|m}}, {{tt|txb|mewiya|f}}
* Tulu: {{tt+|tcy|ಪಿಲಿ}}
* Turki: {{tt+|tr|kaplan}}
*: Turki Usmaniyah: {{tt|ota|قپلان|tr=kaplan}}, {{t|ota|پلنك|tr=peleng}}, {{t|ota|ببر|tr=bebr, bebir}}
* Turkmen: {{tt|tk|gaplaň}}
* Tuvan: {{tt|tyv|пар}}
* Udihe: {{tt|ude|кути|tr=kuti}}, {{tt|ude|амба|tr=amba}}
* Udmurt: {{tt|udm|юлбарыс}}
* Ukraine: {{tt+|uk|тигр|m}}
* Urak Lawoi': {{tt|urk|brutat}}
* Urdu: {{tt+|ur|شیر|m}}, {{tt|ur|باگھ|m}}, {{t|ur|بَبَر|m}}
* Uyghur: {{tt|ug|يولۋاس}}, {{tt|ug|بارس}}
* Uzbek: {{tt+|uz|yoʻlbars}}
* Vietnam: {{tt+|vi|hổ}}, {{tt+|vi|cọp}}, {{tt+|vi|khái}}, {{tt+|vi|kễnh}}, {{tt+|vi|hùm}}
* Volapük: {{tt+|vo|tigrid}}
* Walloon: {{tt+|wa|tigue|m}}
* Welsh: {{tt+|cy|teigr|m}}
* Winnebago: {{t|win|wicąwą kirikiriš}}
* Wolaytta: {{t|wal|maahiya}}
* Wutunhua: {{tt|wuh|dak}}
* Yakut: {{tt|sah|баабыр}}
* Yiddish: {{tt|yi|טיגער|m}}
* Yoruba: {{tt|yo|ẹkùn}}
* Zapotec:
*: Zapotec Segenting: {{tt|zai|beedxeʼ}}
* Zhuang: {{tt|za|guk}}
* Zulu: {{tt+|zu|ithayiga|c5|c6}}
}}
{{ter-bawah}}
===Tesaurus===
* [[macan]].
anpztmimhkiko77527h61ltdnmli64r
344388
344387
2026-05-26T03:39:19Z
Hakimi97
2668
t+en:[[:tiger]] ([[WT:EDIT|Suntingan berbantu gajet]])
344388
wikitext
text/x-wiki
{{wikipedia|Harimau}}
[[Fail:Panthera tigris tigris.jpg|thumb|Harimau belang]]
== Bahasa Melayu ==
===Takrifan===
{{ms-kn}}
# sejenis haiwan [[mamalia]] [[maging]] besar dalam famili [[kucing]] yang berasal dari Asia, khususnya harimau belang, ''Panthera tigris''.
====Kata terbitan====
* mengharimaui: memarahi dengan dahsyat.
===Etimologi===
<!--Daripada bahasa ?-->
===Sebutan===
{{dewan|ha|ri|mau}}
===Tulisan Jawi===
{{ARchar|هريماو}}
===Terjemahan===
{{ter-atas|Haiwan mamalia ''Panthera tigris''}}{{multitrans|data=
* Abkhaz: {{tt|ab|атигр}}
* Aceh: {{tt|ace|rimuëng}}
* Afrikaans: {{tt+|af|tier}}
* Ahom: {{tt|aho|𑜏𑜢𑜤𑜰𑜫}}, {{tt|aho|𑜏𑜢𑜤𑜈𑜫}}
* Aiton: {{tt|aio|ꩬိုဝ်}}
* Alabama: {{tt|akz|kowibasbaki}}, {{tt|akz|kowiɬahkachi}}
* Albania: {{tt+|sq|tigër|m}}
* Altai:
*: Altai Utara: {{t|atv|марс}}, {{t|atv|парс}}
*: Altai Selatan: {{t|alt|барс}}
* Amhara: {{tt|am|ነብር}}
* Amuzgo:
*: Amuzgo Guerrero: {{tt|amu|kítziaⁿ}}
* Angami: {{tt|njm|tekhu}}
* Ao: {{t|njo|keyi}} {{q|Chungli}}
* Aoheng: {{tt|pni|sengiru}}, {{tt|pni|sengiro}}, {{tt|pni|singiro}}
* Arab: {{tt+|ar|نِمْر|m}}, {{tt+|ar|بَبْر|m}}
*: Arab Mesir: {{tt|arz|نمر|m|tr=nimr}}
*: Arab Hijaz: {{t|acw|نمر|m|tr=nimir}}
* Aram:
*: Neo-Aram Assyria: {{t-needed|aii}}
*: Suryani Klasik: {{tt|syc|ܛܝܓܪܝܣ|f|tr=ṭīḡrīs}}, {{tt|syc|ܒܒܪܐ|m|ts=bbrʾ}}
*: Aram Babylon Ibrani: {{tt|arc|טִיגְרִיס|m|tr=ṭîḡrîs}}
* Archi: {{tt|aqc|цӏиркъ}}
* Armenia: {{tt+|hy|վագր}}
* Assam: {{tt|as|ঢেঁকীয়াপতীয়া বাঘ}}, {{tt|as|বাঘ}} {{q|hypernym}}
* Asturias: {{tt+|ast|tigre|m}}
* Atayal: {{t|tay|zkliʼ}}
* Avar: {{tt|av|цӏиркъ}}
* Awadhi: {{tt|awa|बाघ|m}}
* Azeri: {{tt+|az|pələng}}
* Melayu Baba: {{tt|mbf|arimo}}
* Bahnar: {{tt|bdq|kla}}
* Bali: {{tt|ban|macan}}
* Baluchi: {{tt|bal|مزار|tr=mazár}}
* Bashkir: {{tt|ba|юлбарыҫ}}
* Basque: {{tt+|eu|tigre}}
* Batak:
*: Batak Mandailing: {{tt+|btm|babiat}}
*: Batak Toba: {{tt|bbc|babiat}}, {{tt|bbc|babiak}}, {{tt|bbc|ompung}}, {{tt|bbc|ompungi}}
* Batek: {{tt|btq|yah}}, {{tt|btq|ayok}}, {{tt|btq|ayõng}}, {{tt|btq|pangan}}, {{tt|btq|ãp}}, {{tt|btq|iyah}}, {{tt|btq|bek}}, {{tt|btq|gayi}}
* Belarus: {{tt|be|тыгр|m}}, {{tt|be|ты́гра|f}} {{qualifier|colloquial}}
* Bengali: {{tt+|bn|বাঘ}}
* Berawan: {{tt|lod|upo}}
* Besisi: {{tt|mhe|a'a}}, {{tt|mhe|a'ak}}, {{tt|mhe|tuéh}}, {{tt|mhe|malap}}
* Bhojpuri: {{t|bho|बाघ}}
* Bidayuh:
*: Bidayuh Bau: {{tt|sne|rimoung}}
*: Bidayuh Bukar-Sadung: {{tt|sdo|limo}}
* Bouyei: {{tt|pcc|gugt}}, {{tt|pcc|duezgugt}}
* Breton: {{tt+|br|tigr|m}}
* Bugis: {{tt|bug|macang}}
* Bulgaria: {{tt+|bg|ти́гър|m}}
* Bundeli: {{tt|bns|नाहर|m}}
* Burma: {{tt+|my|ကျား}}
* Burusu: {{tt|bqr|mintik inon}}
* Catalonia: {{tt+|ca|tigre|m}}
* Cebuano: {{tt|ceb|tigre}}
* Tamazight Atlas Tengah: {{tt|tzm|ⴰⵖⵉⵍⴰⵙ|m}}
* Cham:
*: Cham Timur: {{tt|cjm|rimông}}, {{tt|cjm|ramông}}
*: Cham Barat: {{tt|cja|ramông}}
* Chechen: {{tt|ce|цӏоькъалом}}
* Cherokee: {{tt|chr|ᏢᏓᏥ ᏧᎶᎸᏗ}}
* Chewong: {{tt|cwg|kle}}, {{tt|btq|keli}}
* Cina:
*: Kantonis: {{tt|yue|老虎|tr=lou5 fu2}}
*: Dungan: {{tt|dng|лохў}}, {{tt|dng|хў}}
*: Min Timur: {{tt|cdo|老虎|tr=lâu-hū}}
*: Gan: {{tt|gan|老虎|tr=lau3 'fu3}}
*: Hakka: {{tt|hak|老虎|tr=lo-fú}}
*: Hokkien: {{tt+|nan-hbl|虎|tr=hó͘}}
*: Jin: {{tt|cjy|老虎|tr=lau2 hu2}}
*: Mandarin: {{tt+|cmn|老虎|tr=lǎohǔ}}, {{tt+|cmn|虎|tr=hǔ}} {{q|klasik atau dalam bentuk kata majmuk}}
*: Wu: {{tt|wuu|老虎}}
*: Xiang: {{tt|hsn|老虎|tr=lau3 fu}}
* Chru: {{tt|cje|rơmòg}}
* Circassia:
*: Circassia Timur: {{tt+|kbd|къаплъэн}}, {{tt|kbd|хьэщомыщ}}
*: Circassia Barat: {{tt|ady|къаплъэн}}, {{tt|ady|къэплъан}}
* Koptik: {{tt|cop|ϫⲓⲕⲣⲓⲥ|m}}
* Cornwall: {{tt|kw|tiger|m}}, {{tt+|kw|tygra}}
* Corsica: {{tt+|co|tigru|m}}
* Cree:
*: Montagnais: {{tt|moe|minashkuau-minush}}
* Czech: {{tt+|cs|tygr|m}}
* Denmark: {{tt+|da|tiger|c}}
* Dhivehi: {{tt|dv|މިނިކާވަގަ}}
* Dongxiang: {{tt|sce|basi}}
* Dusun:
*: Kadazandusun: {{tt|dtp|rimau}}
* Dutch: {{tt+|nl|tijger|m}}
* Dzongkha: {{tt|dz|སྟག}}
* Embaloh: {{tt|emb|baro}}
* Enggano: {{tt|eno|nimau}}
* Erzya: {{tt|myv|бабри}}
* Esperanto: {{tt+|eo|tigro}}
* Estonia: {{tt|et|tiiger}}
* Faroe: {{tt|fo|tikari|m}}
* Finland: {{tt+|fi|tiikeri}}
* Perancis: {{tt+|fr|tigre|m}}, {{tt+|fr|tigresse|f}}
* Frisia:
*: Frisia Barat: {{tt+|fy|tiger|c}}
* Galicia: {{tt+|gl|tigre|m}}, {{tt|gl|tigresa|f}}
* Gayo: {{tt|gay|kule}}
* Georgia: {{tt+|ka|ვეფხვი}}
* Jerman: {{tt+|de|Tiger|m}}, {{tt+|de|Tigerin|f}}, {{tt|de|Tigermännchen|n}} {{qualifier|male}}, {{tt|de|Tigerweibchen|n}} {{qualifier|female}}
*: Jerman Tanah Tinggi Pertengahan: {{tt|gmh|tigertier|n}}
*: Jerman Tanah Tinggi Kuno: {{tt|goh|tigirtior|n}}, {{tt|goh|tigritior|n}}
* Gondi: {{tt|gon|బుర్కల్|tr=burkal}}
* Gong: {{tt|ugo|เดือ}}
* Yunani: {{tt+|el|τίγρη|m|f}}, {{tt+|el|τίγρης|m}}
*: Yunani Kuno: {{tt|grc|τίγρις|m|f}}
* Greenland: {{tt+|kl|tiigeri}}
* Guarani:
*: Guarani Paraguay: {{tt-check|gug|jaguarete}}
* Gujarati: {{tt+|gu|વાઘ|m}}
* Kreol Haiti: {{tt|ht|tig}}
* Haroi: {{tt|hro|lĕmung}}
* Ibrani: {{tt+|he|טִיגְרִיס|m|tr=tígris}}
* Hindi: {{tt+|hi|बाघ|m}}, {{tt+|hi|व्याघ्र|m}}, {{tt+|hi|नाहर|m}}, {{tt+|hi|केहर|m}}
* Hmong:
*: A-Hmao: {{t|hmd|𖼯𖽙𖾑}}
*: Hmong Putih: {{tt|mww|tsov}}
* Hungary: {{tt+|hu|tigris}}
* Iban: {{tt|iba|remaung}}
* Iceland: {{tt+|is|tígur|m}}
* Ida'an: {{tt|dbj|kakkang}} (young)
* Ido: {{tt+|io|tigro}}
* Igbo: {{t|ig|agụ}}
* Indonesia: {{tt+|id|harimau}}
* Ingrian: {{tt|izh|tigra}}
* Ingush: {{tt|inh|цӀокъ}}
* Interlingua: {{tt|ia|tigre}}
* Irish: {{tt+|ga|tíogar|m}}
* Itali: {{tt+|it|tigre|f}}
* Jah Hut: {{tt|jah|kelaq}}
* Jepun: {{tt+|ja|虎|tr=とら, tora}}
* Jarai: {{tt|jra|rờmōng}}
* Jawa: {{tt+|jv|macan}}, {{tt|jv|gémbong}} (ngoko), {{tt+|jv|gogor}} (young), {{tt|jv|sima}} (krama), {{tt+|jv|wiyagra}}, {{tt+|jv|sardula}}, {{tt+|jv|bowong}}
*: Jawa Kuno: {{tt|kaw|macan}}, {{t|kaw|bowoṅ}}, {{t|kaw|harimoṅ}}, {{t|kaw|hariwyāghra}}, {{t|kaw|moṅ}}, {{t|kaw|mṛgādhipa}}, {{t|kaw|mṛganātha}}, {{t|kaw|mṛgapati}}, {{t|kaw|mṛgaprabhu}}, {{t|kaw|mṛgarāja}}, {{t|kaw|mṛgendra}}, {{t|kaw|puhun}}, {{t|kaw|samoṅ}}, {{t|kaw|śārdūla}}, {{t|kaw|śārdūlākṛti}}, {{t|kaw|wasari}}, {{t|kaw|wasarya}}, {{t|kaw|wyāghra}}
* Jehai: {{tt|jhi|ap}}, {{tt|jhi|ju'ok}}, {{tt|jhi|baling}}, {{tt|jhi|putew}}
* Kalmyk: {{tt|xal|ирвск}}
* Kannada: {{tt+|kn|ಹುಲಿ}}
* Karachay-Balkar: {{tt|krc|къаплан|tr=qaplan}}
* Karen:
*: Karen Pa'o: {{tt|blk|ကေ}}
* Kazakh: {{tt|kk|жолбарыс}}
* Kelabit: {{tt|kzi|balang}}
* Kensiu: {{tt|kns|émet}}, {{tt|kns|tayok}}, {{tt|kns|ong}}
* Kerinci: {{tt|kvr|imaw}}
* Khalaj: {{t|klj|bəbr}}, {{t|klj|palang}}
* Khamti: {{t-needed|kht}}
* Khasi: {{tt|kha|khla}}
* Khmer: {{tt+|km|ខ្លា}}, {{tt+|km|ខ្លាធំ}}
* Korea: {{tt+|ko|호랑이}}, {{tt+|ko|범}}
*: Korea Pertengahan: {{tt|okm|범〯}}
* Kristang: {{tt|mcm|trigi}}
* Kubu: {{tt|kvb|mer'ego}}, {{tt|kvb|natong hidup}}
* Kumyk: {{tt|kum|къаплан|tr=qaplan}}
* Kurdi:
*: Kurdi Tengah: {{tt|ckb|بەور}}
*: Kurdi Utara: {{tt+|kmr|piling}}
* Kyrgyz: {{tt+|ky|жолборс}}
* Lampung Api: {{tt|ljp|kumbok}}, {{tt|ljp|lemawong}}, {{tt|ljp|lemameng}}, {{tt|ljp|waw}}, {{tt|ljp|jin}}
* Lao: {{tt+|lo|ເສືອ}}
* Latin: {{tt+|la|tīgris|m|f}}
* Latvia: {{tt|lv|tīģeris|m}}
* Lawangan: {{tt|lbx|timang}}, {{tt|lbx|timaang}}
* Lezgi: {{tt|lez|пеленг}}
* Liguria: {{tt|lij|tîgre|f}}
* Limburg: {{tt+|li|tieger|m}}
* Lisu: {{tt|lis|ꓡꓽ}}
* Lithuania: {{tt+|lt|tigras|m}}
* Jerman Tanah Rendah: {{tt|nds|Tieger|m}}
* Lü: {{tt|khb|ᦵᦉᦲ}}
* Lutuv: {{t|clt|cakyi}}, {{t|clt|kyipuv}}
* Luxembourg: {{tt|lb|Tiger|m}}
* Makedonia: {{tt|mk|тигар|m}}
* Malagasy: {{tt+|mg|trimo}}
* Melayu:
*: Melayu Brunei: {{tt|kxd|haimau}} {{q|Kedayan}}
*: Melayu Barisan: {{tt|pse|setue}}, {{tt|pse|ne'ngau}} {{q|Besemah}}
*: Melayu Barisan: {{tt|pse|setuau}}, {{tt|pse|setuo}} {{q|Serawai}}
*: Melayu Kutai Kota Bangun: {{tt|mqg|remaong}}
* Malayalam: {{tt+|ml|കടുവ}}
* Malta: {{tt|mt|tigra|f}}
* Manchu: {{tt|mnc|ᡨᠠᠰᡥᠠ}}, {{tt|mnc|ᠮᡠᡥᠠᠨ}} {{qualifier|male}}, {{tt|mnc|ᠪᡳᡵᡝᠨ}} {{qualifier|female}}, {{tt|mnc|ᡨᠠᡵᡶᡠ}}
* Manx: {{tt|gv|çheegyr|m}}, {{tt|gv|teigyr|m}}
* Māori: {{tt|mi|taika}}
* Mapudungun: {{tt|arn|nahuel}}
* Marathi: {{tt|mr|वाघ|m}}
* Mazanderani: {{tt|mzn|پلنگ|tr=paleng}}, {{tt|mzn|ببر|tr=baber }}, {{tt|mzn|دورگ|tr=dorag}}
* Melanau:
*: Melanau Tengah: {{tt|mel|rimau}}, {{tt|mel|rimau baleng}}
* Inggeris Pertengahan: {{tt|enm|tygre}}
* Minangkabau: {{tt+|min|inyiak}}
* Mingrelia: {{tt|xmf|ჸილო}}
* Minriq: {{tt|mnq|lodap}}, {{tt|mnq|ap}}
* Mohawk: {{t|moh|takoʼskó꞉wa}}
* Mon: {{tt+|mnw|ကၠ|tr=klaˀ}}
* Mongol:
*: Sirilik: {{tt+|mn|бар}}
*: tulisan Mongol: {{tt|mn|ᠪᠠᠷᠰ}}
* Muong: {{tt|mtq|khảl}}
* Murut:
*: Murut Serudung: {{tt|srk|takinon}}
* Naga:
*: Naga Khiamniungan: {{t|kix|khāu}}
* Nanai: {{tt|gld|амбан}}
* Navajo: {{tt|nv|náshdóítsoh noodǫ́zígíí}}
* Nepal: {{tt+|ne|बाघ}}
* Ngaju: {{tt|nij|haramaung}}
* Nivkh: {{tt|niv|ат}}, {{tt|niv|иғлуладь}}
* Nogai: {{tt|nog|йолбарыс}}
* Norwey:
*: Bokmål: {{tt+|nb|tiger|m}}
*: Nynorsk: {{tt+|nn|tiger|m}}
* Nuosu: {{tt|ii|ꆿ}}
* Occitania: {{tt+|oc|tigre|m}}
* Odia: {{tt+|or|ବାଘ}}
* Slav Gereja Kuno: {{tt|cu|тигръ|m}}
* Inggeris: {{t+|en|tiger}}
* Inggeris Kuno: {{tt|ang|tiger|m}}
* Oromo: {{tt|om|qeerramsa}}
* Oroqen: {{tt|orh|ʊta꞉tʃi}}
* Ossetia: {{tt|os|тигр}}
* Pacoh: {{tt|pac|cula}}
* Pali:
*: Bengal: {{tt|pi|ব্যগ্ঘ|m}}
*: Burma: {{tt|pi|ဗျဂ္ဃ|m}}
*: Devanagari: {{tt|pi|ब्यग्घ|m}}
*: Khmer: {{tt|pi|ព្យគ្ឃ|m}}
*: Latin: {{tt|pi|byaggha|m}}
*: Sinhala: {{tt|pi|බ්යග්ඝ|m}}
*: Tai Tham: {{tt|pi|ᨻ᩠ᨿᨣ᩠ᨥ|m}}
*: Thai: {{tt|pi|พฺยคฺฆ|m}}
* Rusyn Pannonia: {{t|rsk|тиґриш|m}}, {{t|rsk|тиґер|m}}
* Pashto: {{tt|ps|پړانګ|m|tr=pṛāng}}
* Pawnee: {{tt|paw|pakstítkukiic}}
* Penan:
*: Penan Timur: {{tt|pez|piad}}
*: Penan Barat: {{tt|pne|biat}}
* Parsi:
*: Dari: {{tt|prs|بَبْر}}
*: Parsi Iran: {{tt|fa-ira|بَبْر}}
* Phake: {{t-needed|phk}}
* Plautdietsch: {{tt|pdt|Tieja|m}}
* Poland: {{tt+|pl|tygrys|m-an}}
* Portugis: {{tt+|pt|tigre|m}}
* Prakrit:
*: Prakrit Ardhamagadhi: {{tt|pra-ard|𑀯𑀕𑁆𑀖|m}}
*: Prakrit Maharastri: {{tt|pra-mah|𑀯𑀕𑁆𑀖|m}}
*: Prakrit Sauraseni: {{tt|pra-sau|𑀯𑀕𑁆𑀖|m}}
* Tubu Punan: {{tt|puj|vi'at}}, {{tt|puj|fi'at}}
* Punjabi:
*: Gurmukhi: {{tt+|pa|ਸ਼ੇਰ|m}}, {{tt|pa|ਬਾਘ|m}}
*: Punjabi Barat: {{tt+|pnb|شیر|m}}, {{tt|pnb|باگھ|m}}
* Quechua: {{tt|qu|uthurunku}}
* Rade: {{tt|rad|êmông}}
* Rejang: {{tt|rej|imêu}}
* Roglai:
*: Roglai Utara: {{tt|rog|lumõng}}
* Rohingya: {{tt|rhg|bag}}
* Romagnol: {{tt|rgn|tigra|f}}
* Romania: {{tt+|ro|tigru|m}}
* Rungus: {{tt|drg|orimau}}
* Rusia: {{tt+|ru|тигр|m-an}}
* Saek: {{tt|skb|กู̄ก}}
* Salako: {{tt|knx|rimong}}
* Sanskrit: {{tt+|sa|व्याघ्र|m}}
* Santali: {{tt+|sat|ᱛᱟᱹᱨᱩᱵ}}
* Saurashtra: {{tt|saz|ꢮꢵꢔ꣄}}
* Scots: {{tt|sco|teeger}}
* Semai: {{tt|sea|atañ}}, {{tt|sea|kaap}}, {{tt|sea|berenggas}}, {{tt|sea|raak}}, {{tt|sea|mameek}}, {{tt|sea|mergas}}, {{tt|sea|bergas}}, {{tt|sea|nyuuq}}, {{tt|sea|keek}}, {{tt|sea|bagòr}}, {{tt|sea|kaam}}, {{tt|sea|rerok}}
* Semaq Beri: {{tt|szc|gayit}}
* Semnam: {{tt|ssm|kmuuc}}
* Serbo-Croatia:
*: Sirilik: {{tt|sh|тигар|m}}
*: Latin: {{tt+|sh|tigar|m}}
* Shan: {{tt+|shn|သိူဝ်}}
* Sian: {{tt|spg|piyat}}
* Siang: {{tt|sya|hôrômaung}}
* Sicily: {{tt+|scn|tigri|f}}, {{tt|scn|trighi|f}}
* Sindhi: {{tt|sd|واگھُ|m|tr=vāghu}}
* Sinhala: {{tt+|si|කොටියා}}
* Slovak: {{tt+|sk|tiger|m}}
* Slovene: {{tt+|sl|tiger|m}}
* Somali: {{tt+|so|shabeel}}
* Sorbia:
*: Sorbia Hilir: {{tt|dsb|tiger|m}}
*: Sorbia Hulu: {{tt|hsb|tiger|m}}
* Sepanyol: {{tt+|es|tigre|m}}
* Sunda: {{tt|su|lodaya}}, {{tt+|su|maung}}, {{tt+|su|aom}} (young), {{tt|su|rimau}}
* Swahili: {{tt|sw|chui milia}}, {{tt+|sw|simba marara|c9|c10}}
* Sweden: {{tt+|sv|tiger|c}}
* Sylheti: {{tt|syl|ꠛꠣꠊ}}
* Tabasaran: {{tt|tab|пеленг}}
* Tagalog: {{tt+|tl|tigre}}
* Tai Dam: {{tt|blt|ꪹꪎ}}
* Tai Nüa: {{tt|tdd|ᥔᥫᥴ}}
* Tajik: {{tt+|tg|бабр}}
* Tamil: {{tt+|ta|புலி}}
* Tarao: {{tt|tro|yokpi}}
* Tatar: {{tt+|tt|юлбарыс}}
* Telugu: {{tt+|te|పులి|?}}, {{tt+|te|వ్యాఘ్రము|m}}
* Temiar: {{tt|tea|mamuh}}, {{tt|tea|merges}}, {{tt|tea|mamuug}}, {{tt|tea|aab}}
* Temoq: {{tt|tmo|barangmoh}}, {{tt|tmo|daying}}, {{tt|tmo|mĕ'ong}}, {{tt|tmo|tĕhoqpolan}}, {{tt|tmo|pĕn-yow}}
* Ten'edn: {{tt|tnz|o'}}
* Thai: {{tt+|th|เสือ}}, {{tt+|th|โคร่ง|alt=เสือโคร่ง|tr=sʉ̌ʉa-krôong}}
* Tibet: {{tt|bo|སྟག}}
* Tigrinya: {{tt|ti|ነብሪ}}
* Tobilung: {{tt|tgb|mondou}}, {{tt|tgb|tatanansad}}
* Tocharia B: {{tt|txb|mewiyo|m}}, {{tt|txb|mewiya|f}}
* Tulu: {{tt+|tcy|ಪಿಲಿ}}
* Turki: {{tt+|tr|kaplan}}
*: Turki Usmaniyah: {{tt|ota|قپلان|tr=kaplan}}, {{t|ota|پلنك|tr=peleng}}, {{t|ota|ببر|tr=bebr, bebir}}
* Turkmen: {{tt|tk|gaplaň}}
* Tuvan: {{tt|tyv|пар}}
* Udihe: {{tt|ude|кути|tr=kuti}}, {{tt|ude|амба|tr=amba}}
* Udmurt: {{tt|udm|юлбарыс}}
* Ukraine: {{tt+|uk|тигр|m}}
* Urak Lawoi': {{tt|urk|brutat}}
* Urdu: {{tt+|ur|شیر|m}}, {{tt|ur|باگھ|m}}, {{t|ur|بَبَر|m}}
* Uyghur: {{tt|ug|يولۋاس}}, {{tt|ug|بارس}}
* Uzbek: {{tt+|uz|yoʻlbars}}
* Vietnam: {{tt+|vi|hổ}}, {{tt+|vi|cọp}}, {{tt+|vi|khái}}, {{tt+|vi|kễnh}}, {{tt+|vi|hùm}}
* Volapük: {{tt+|vo|tigrid}}
* Walloon: {{tt+|wa|tigue|m}}
* Welsh: {{tt+|cy|teigr|m}}
* Winnebago: {{t|win|wicąwą kirikiriš}}
* Wolaytta: {{t|wal|maahiya}}
* Wutunhua: {{tt|wuh|dak}}
* Yakut: {{tt|sah|баабыр}}
* Yiddish: {{tt|yi|טיגער|m}}
* Yoruba: {{tt|yo|ẹkùn}}
* Zapotec:
*: Zapotec Segenting: {{tt|zai|beedxeʼ}}
* Zhuang: {{tt|za|guk}}
* Zulu: {{tt+|zu|ithayiga|c5|c6}}
}}
{{ter-bawah}}
===Tesaurus===
* [[macan]].
qtg2a92aais8l9xvwmc0sm81kwlcmsw
kami
0
4673
344361
337854
2026-05-25T14:31:21Z
Ultron90
4762
344361
wikitext
text/x-wiki
{{wikipedia|Kami}}
==Bahasa Melayu==
===Kata ganti nama===
{{ms-kgn|j=کامي}}
# [[saya]] dan sekurang-kurangnya seorang lain [[kecuali]] orang yang ditujukan kata-kata.
====Bentuk alternatif====
====Bahasa isyarat====
<gallery>
BIM kami.webm|[[Fail:BIM kami.gif|kiri|frameless]]Bahasa Isyarat Malaysia
</gallery>
===Etimologi===
Daripada {{inh|ms|poz-mly-pro|*kami}}, daripada {{inh|ms|poz-pro|*kami}}, daripada {{inh|ms|map-pro|*kami}}.
===Sebutan===
* {{dewan|ka|mi}}
* {{AFA|ms|/ka.mi/}}
* {{rima|ms|i}}
* {{penyempangan|ms|ka|mi}}
* {{audio|ms|Ms-MY-kami.ogg|Audio (MY)}}
===Terjemahan===
{{ter-atas|saya dan orang lain kecuali yang saya tujukan kata-kata}}
* Abkhaz: {{t|ab|ҳара|sc=Cyrl}}
* Afar: {{t|aa|nanu}}
* Afrikaans: {{t|af|ons}}
* Akan: {{t|ak|yɛn}}
* Albania: {{t+|sq|ne}}
* Alviri-Vidari: {{t|avd|جیمه|tr=jime}}
* Amhara: {{t|am|እኛ}}
* Arab: {{t|ar|نَحْنُ|p}}
*: Arab Mesir: {{t|arz|احنا|tr=ʾíḥna}}
*: Arab Tunisia: {{t|aeb|احنا|m|f|alt=أَحْنَا|tr=ʾaḥnā}}
* Aragon: {{t|an|nusatros}} {{qualifier|masculine}}, {{t|an|nusatras}} {{qualifier|feminine}}
* Aramia:
*: Ibrani: {{t|arc|אֲנַחְנָא|tr=ʾănaḥnā}}, {{t|arc|אֲנַן|tr=ʾănan}}
*: Suryani: {{t|arc|ܐ̄ܢܲܚܢܲܢ|tr=naḥnan}}, {{t|arc|ܚ̱ܢܲܢ|tr=ḥənan}}
* Armenia: {{t+|hy|մենք}}
*: Armenia Lama: {{t|xcl|մեք}}
* Aromania: {{t|rup|noi}}
* Assam: {{t|as|আমি}}
* Asturia: {{t+|ast|nosotros|m-p}}, {{t+|ast|nosotras|f-p}}
* Avar: {{t|av|ниж}}
* Avesta: {{t|ae|𐬬𐬀𐬉𐬨}}, {{t|ae|𐬬𐬁}} {{qualifier|dual}}
* Aymara: {{t|ay|nanaka}}
* Azerbaijani: {{t+|az|biz}}
* Bahasa Isyarat Amerika: [[1^o-f@IpsiChest-FingerBack RoundHoriz 1^o-f@ContraChest-FingerBack]] (juga bentuk kita dan kami (tidak tersenarai), juga sebagai penggabungan angka)
* Bakhtiari: {{t|bqi|ایما|tr=imâ}}
* Bambara: {{t|bm|an}}
* Bashkir: {{t|ba|беҙ|sc=Cyrl}}
* Basque: {{t+|eu|gu}}
* Bavaria: {{t|bar|mia}}
* Beja: {{t|bej|hinin}}
* Belarus: {{t+|be|мы}}
* Bengali: {{t|bn|আমরা|sc=Beng}}
* Bislama: {{qualifier|kami dua}} {{t|bi|mitufala}}, {{qualifier|kami tiga}} {{t|bi|mitrifala}}, {{qualifier|kami jamak}} {{t|bi|mifala}}
* Breton: {{t+|br|ni}}
* Bulgaria: {{t+|bg|ни́е}}
* Burma: {{t|my|ကျုပ်တို့|sc=Mymr}}, {{t+|my|တို့|sc=Mymr}}, {{t|my|ကျွန်တော်တို့|sc=Mymr}} {{qualifier|penutur lelaki}}, {{t|my|ကျွန်မတို့|sc=Mymr}} {{qualifier|penutur perempuan}}, {{t|my|ငါတို့|sc=Mymr}} {{qualifier|informal}}
* Catalan: {{t+|ca|nosaltres}}
* Chamicuro: {{t|ccc|a'ti}}
* Chechen: {{t|ce|вай}}
* Chichewa: {{t|ny|ife}}
* Cina:
*: Dungan: {{t|dng|вәму}}
*: Gan: {{t|gan|我個俚}}, {{t|gan|我个俚|tr=ngo3 go li}}, {{t|gan|我等|tr=ngo3 diin}}
*: Hakka: {{t|hak|𠊎兜|tr=ngài-têu}}, {{t|hak|𠊎等|tr=ngài-tén, ngài-tên, ngài-nên}}, {{t|hak|𠊎等人|tr=ngai2 dên1 ngin2 / ngai2 dên3 ngin2}} {{qualifier|Meixian}}
*: Jin: {{t|cjy|我們}}, {{t|cjy|我们|tr=ghe2 me}}, {{t|cjy|俺們}}, {{t|cjy|俺们|tr=ghan2 me / gha2 me}}
*: Kantonis: {{t|yue|我哋|tr=ngo5 dei6|sc=Hani}}, {{t|yue|我們}}, {{t|yue|我们|tr=ngo3 men2-1}} {{qualifier|sastera}}
*: Mandarin: {{t+|cmn|我們|sc=Hani}}, {{t+|cmn|我们|tr=wǒmen|sc=Hani}} {{qualifier|umum dalam kebanyakan dialek, tetapi "kami" dalam beberapa dialek}}, {{t+|cmn|俺們}}, {{t+|cmn|俺们|tr=ǎnmen}} {{qualifier|dialek, China Utara}}
*: Min Bei: {{t|mnp|我人|tr=uòi-nêng}}
*: Min Dong: {{t|cdo|我各儂}}, {{t|cdo|我各侬|tr=nguāi-gáuk-nè̤ng}}
*: Min Nan: {{t+|nan|阮|tr=góan, gún|sc=Hani}}
*: Teochew: {{t+|nan|阮|tr=ng2|sc=Hani}}
*: Wu: {{t|wuu|阿拉|tr=aq la, aq laq}} {{qualifier|Shanghai}}, {{t|wuu|伲|tr=nyi}} {{qualifier|Suzhou}}
*: Xiang: {{t|hsn|我們}}, {{t|hsn|我们|tr=ngo3 men}}
* Chukchi: {{t|ckt|моргынан|tr=morgynan}}
* Chuvash: {{t|cv|эпир|sc=Cyrl}}
* Cree: {{t|cr|ᓃᔭᓈᓐ}}, {{t|cr|ᓃᔭᓈᐣ}}
* Czech: {{t+|cs|my}}
* Dalmatia: {{t|dlm|nu}}
* Denmark: {{t+|da|vi}}
* Dutch: {{t+|nl|wij}}, {{t+|nl|we}}
* Dyirbal: {{t|dbl|ŋaliɖi|d}}, {{t|dbl|ŋanaɖi|p}}
* Efik: {{t|efi|nnyin}}
* Esperanto: {{t+|eo|ni}}
* Estonia: {{t+|et|meie}}, {{t+|et|me}}
* Extremadura: {{t|ext|nusotrus}}
* Fiji: {{qualifier|dual}} {{t-check|fj|keirau}}, {{qualifier|[[paucal]]}} {{t-check|fj|keitou}}, {{t-check|fj|keimami|p}}
* Finland: {{t+|fi|me}}, {{t+|fi|myö}} {{q|dialectal}}
* Frisia Barat: {{t+|fy|wy}}
* Friulia: {{t|fur|nô}}, {{t|fur|noaltris}}
* Galicia: {{t+|gl|nós|m-p|f-p}}
* Georgia: {{t|ka|ჩვენ|sc=Geor}}
* German: {{t+|de|wir}}
*: Alemannic German: {{t|gsw|mir}}
* Greek: {{t+|el|εμείς}} (emeís)
* Ancient Greek: {{t|grc|ἡμεῖς}}
* Gurani: {{t|hac|ئێمە|tr=êmæ|sc=fa-Arab}}
* Hausa: {{qualifier|independent form}} {{t-check|ha|múu}}, {{qualifier|perfective 1}} {{t-check|ha|mún}}, {{qualifier|perfective 2}} {{t-check|ha|múkà}}, {{qualifier|neg. perfective}} {{t-check|ha|bàmù...bá}}, {{qualifier|future}} {{t-check|ha|záamù}}, {{qualifier|predictive}} {{t-check|ha|mâa}}, {{qualifier|habitual}} {{t-check|ha|múkàn}}, {{qualifier|subjunctive}} {{t-check|ha|mù}}, {{qualifier|continuous 1}} {{t-check|ha|múnàa}}, {{qualifier|continuous 2}} {{t-check|ha|múkè(e)}}, {{qualifier|neg. continuous}} {{t-check|ha|báamàa}}
* Hawaii: {{qualifier|dual}} {{t|haw|māua}}, {{t|haw|mākou|p}}
* Hindi: {{t+|hi|हम}}
* Hopi: {{t|hop|itam}}
* Hungary: {{t+|hu|mi}}
* Ibrani: {{t+|he|אֲנַחְנוּ|tr=anákhnu}}, {{t+|he|אָנוּ|tr=ánu}}
* Iceland: {{t+|is|við}}
* Ido: {{t+|io|ni}}
* Indonesia: {{t+|id|kami}}
* Inggeris: {{t+|en|we}} {{qualifier|umum}}
* Interlingua: {{t+|ia|nos}}
* Irish: {{t|ga|muid}} {{qualifier|conjunctive}}, {{t|ga|sinn}} {{qualifier|disjunctive}}, {{t|ga|muidne}}, {{t|ga|sinne}} {{qualifier|emphatic}}
*: Old Irish: {{t|sga|sní}}
* Istriot: {{t|ist|nu}}
* Itali: {{t+|it|noi}}, {{t|it|noialtri}}
* Jepun: {{t+|ja|私達|tr=わたしたち, watashitachi}}, {{t|ja|我ら|tr=われら, warera}}, {{t+|ja|我々|tr=われわれ, wareware}}, {{t|ja|僕ら|tr=ぼくら, bokura}}, {{qualifier|mainly vulgar/informal}} {{t|ja|俺達|tr=おれたち, oretachi}}, {{qualifier|dialect}} {{t|ja|俺等|tr=おいら, oira}}, {{t+|ja|うち|tr=uchi|sc=Jpan}}, {{t|ja|僕達|tr=ぼくたち, bokutachi|sc=Jpan}}, {{t|ja|私共|tr=わたしども, watashidomo|alt=私ども|sc=Jpan}}
* Kalmyk: {{t|xal|бидн|sc=Cyrl}}
* Kannada: {{t+|kn|ನಾವು|sc=Knda}}
* Kashub: {{t|csb|më}}
* Kazakh: {{t+|kk|біз|sc=Cyrl}}
* Khmer: {{t+|km|យើង|tr=yəəng|sc=Khmr}}
* Kikuyu: {{t|ki|ithuĩ}}
* Korea: {{t+|ko|우리}}, {{t+|ko|저희}} {{qualifier|humble}}
* Kurdish: {{t+|ku|em}}, {{t+|ku|me}}
* Kyrgyz: {{t+|ky|биз|sc=Cyrl}}
* Ladino: {{t|lad|mozotros}}, {{t|lad|מוזוטרוס|sc=Hebr}}
* Laboya: {{t|lmy|yitta}} {{qualifier|inclusive}}
* Lao: {{t|lo|ພວກເຮົາ}}
* Latgale: {{t|ltg|mes}}
* Latin: {{t+|la|nōs}}
* Latvia: {{t+|lv|mēs}}
* Lithuania: {{t+|lt|mes}}
* Low German: {{t+|nds|wi}}
* Macedonia: {{t|mk|ние}}
* Manchu: {{t|mnc|ᠪᡝ|tr=be}}
* Manx: {{t|gv|mayd}}, {{t|gv|shin}}, ''emphatic'' {{t|gv|shinyn}}
* Maori: {{t|mi|māua|d}}, {{t|mi|mātou|p}}
* Mazanderani: {{t|mzn|اما|tr=amâ|sc=ps-Arab}}
* Mon: {{t|mnw|ပိုဲ|tr=poi}}
* Mongolia: {{t+|mn|бид|sc=Cyrl}}
* Mòcheno: {{t|mhn|biar}}
* Nahuatl Klasik: {{t|nci|tehhuān}}, {{t|nci|tehhuāntin}}
* Navajo: {{t|nv|nihí|sc=nv-Latn}} ''duoplural'', {{t|nv|danihí|p|sc=nv-Latn}}
* Neapolitan: {{t|nap|nuje}}
* Nepali: {{t+|ne|हामी|sc=Deva}}
* Ngarrindjeri: {{t|nay|ngurn}}
* Norway:
*: Bokmål: {{t+|no|vi}}
*: Nynorsk: {{t+|nn|me}}, {{t|nn|vi}}
* Novial: {{qualifier|1,2}} {{t|nov|nus}}
* Occitan: {{t+|oc|nos}}, {{t+|oc|nosautres}}
* Ojibwe: {{t|oj|niinawind}}
* Old East Slavic: {{t|orv|мꙑ}}
* Old English: {{qualifier|dual}} {{t+|ang|wit|sc=Latinx}}, {{t+|ang|wē|p|sc=Latinx}}
* Old Turkic: {{t|otk|𐰋𐰃𐰕|tr=biz}}
* Parsi: {{t+|fa|ما|tr=mâ}}
* Pashto: {{t|ps|موږ|tr=muẓ̌}}, {{t|ps|مونږ|tr=mung}}
* Perancis: {{qualifier|1,2}} {{t+|fr|nous}} {{qualifier|formal}}, {{t+|fr|on}} {{qualifier|informal}}
*: Perancis Lama: {{t|fro|nos}}
* Pipil: {{t|ppl|tejemet}}, {{t|ppl|tehemet}}
* Poland: {{t+|pl|my}}
* Portugis: {{t+|pt|nós}}, {{t+|pt|a gente}} {{qualifier|informal}}
* Quechua: {{t+|qu|ñuqayku}}, {{t|qu|ñogaiku}}, {{t|qu|nogakuna}}
* Rapa Nui: {{t|rap|maua}} {{qualifier|dual}}, {{t|rap|matou}} {{qualifier|plural}}
* Romania: {{t+|ro|noi}}
* Romansch: {{t|rm|nus}}, {{t|rm|nous}}
* Rusia: {{t+|ru|мы}}
* Rusyn: {{t|rue|мы}}
* Sami Utara: {{t-check|se|moai}} {{qualifier|duaan}}, {{t-check|se|mii|p}}
* Sardinia: {{t|sc|nois}}, {{t|sc|noso}}, {{t|sc|nosu}}
* Scottish Gaelic: {{t|gd|sinn}} {{qualifier|nonemphatic}}, {{t|gd|sinne}} {{qualifier|emphatic}}
* Sepanyol: {{t+|es|nosotros|m}}, {{t+|es|nosotras|f}}
* Serbo-Croatia:
*: Cyril: {{t|sh|mi}}
*: Rumi: {{t|sh|ми}}
* Sicilia: {{t+|scn|nuàutri}}, {{l|scn|nui}}
* Sinhala: {{t+|si|අපි|sc=Sinh}}
* Slavonik Gereja Lama:
*: Cyril: {{t|cu|мꙑ|sc=Cyrs}}, {{t|cu|вѣ}} {{qualifier|duaan, "kami dua"}}
* Slovak: {{t|sk|my}}
* Slovene: {{t+|sl|mí|m}}, {{t|sl|mé|f|n}}
* Sorbian:
*: Lower Sorbian: {{t|dsb|my}}
* Altai Selatan: {{t|alt|бис}}
* Sami Selatan: {{t|sma|mijjieh}}
* Sranan Tongo: {{t|srn|wi}}
* Svan: {{t-needed|sva}}
* Swahili: {{t|sw|sisi}}
* Sweden: {{t+|sv|vi}}
* Tagalog: {{qualifier|bentuk [[ng]]}} {{t-check|tl|namin}}, {{qualifier|[[sa]] form}} {{t+check|tl|amin}}, {{qualifier|unmarked form}} {{t+check|tl|kami}}
* Tajik: {{t+|tg|мо|sc=Cyrl}}
* Tamil: {{t+|ta|நாங்கள்|sc=Taml}}
* Taos: {{t|twf|ną}}
* Tatar: {{t+|tt|без|sc=Cyrl}}
* Telugu: {{t+|te|మేము}}
* Temuan: {{t|tmw|kican}} {{qualifier|Mantra}}, {{t|tmw|kita}}, {{t|tmw|kitan}} {{qualifier|Belandas}}
* Thai: {{t+|th|เรา}}
* Tibet: {{t|bo|ང་ཐསོ}}
* Tigrinya: {{t|ti|ንሕና|sc=Ethi}}
* Tlingit: {{t|tli|uháan}}
* Tok Pisin: {{t|tpi|mipela}}, {{t|tpi|mitupela}} {{qualifier|dual}}
* Turki: {{t+|tr|biz}}
* Turkmen: {{t+|tk|biz}}
* Tuvan: {{t|tyv|бис}}
* Udihe: {{t|ude|бу|tr=bu|sc=Cyrl}}
* Ukraine: {{t+|uk|ми}}
* Urdu: {{t|ur|ہم|tr=ham}}
* Uyghur: {{t+|ug|بىز|sc=ug-Arab}}
* Uzbek: {{t+|uz|biz}}
* Venice: {{t+|vec|noaltri}}, {{t|vec|noantri}}, {{t|vec|nualtri}}, {{t|vec|naltri}}
* Vietnam: {{t+|vi|chúng tôi}}
* Volapük: {{t+|vo|obs}}
* Welsh: {{t|cy|ni}}, {{qualifier|emphatic}} {{t|cy|ninnau}}
* Wolof: {{t|wo|nun}}
* Yagnobi: {{t|yai|мох}}
* Yiddish: {{t|yi|מיר}}
* Yámana: {{t|yag|xan}}
* Zazaki: {{t|zza|ma}}
* Zealandic: {{t|zea|oôns}}, {{t|zea|wulder}}, {{qualifier|unemphatic}} {{t|zea|me}}
* Zhuang: {{t|za|coiq}}
* Zulu: {{t|zu|thina}}
* ǃXóõ: {{t|nmn|īh}}, {{qualifier|emphatic}} {{t|nmn|īhʻī}}, {{t|nmn|īsî}}, {{qualifier|emphatic}} {{t|nmn|īsîʻī}}
{{ter-bawah}}
===Lihat juga===
{{Kata ganti diri bahasa Melayu}}
==Bahasa Indonesia==
* Lihat takrifan bahasa Melayu.
==Bahasa Jepun==
===Kata nama===
{{ja-noun|r|hira=かみ}}
# [[上]]: [[atas]].
# [[神]]: [[dewa]].
# [[紙]]: [[kertas]].
# [[髪]]: [[rambut]].
72jfswvqt7xfdv2apn96085n14zcyvt
πανθαλής
0
11684
344407
246223
2026-05-26T04:07:28Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344407
wikitext
text/x-wiki
==Bahasa Yunani Purba==
===Etimologi===
Daripada {{affix|grc|πᾰν-|θάλλω|-ης|t1=all|t2=untuk berkembang maju, mekar}}.
===Sebutan===
{{grc-IPA|πᾰνθᾰλής}}
===Kata sifat===
{{grc-adj-3rd|πανθαλές}}
# {{lb|grc|syair}} [[berbunga]], [[pemberi]] semua [[kemekaran]]
#*: {{Q|grc|Bacchylides|Odes|13|228-229|passage=τὰν εἰκ ἐτύμως ἄρα Κλειὼ<br>'''πανθαλὴς''' ἐμαῖς ἐνέσταξεν φρασίν {{...}} |trans=Dan jika ia<br>sesungguhnya telah '''berbunga''' [[w:Clio (muse)|Kleio]]<br>yang menerapkan [ia] di dalam hati saya {{...}} }}
====Infleksi====
{{grc-adecl|πανθαλής|πανθαλές}}
====Rujukan====
* {{R:LSJ}}
0vcaeqkr9dbfyg4qtvmtt4mf2uj15yu
344410
344407
2026-05-26T04:09:35Z
Hakimi97
2668
344410
wikitext
text/x-wiki
==Bahasa Yunani Purba==
===Etimologi===
Daripada {{affix|grc|πᾰν-|θάλλω|-ης|t1=all|t2=untuk berkembang maju, mekar}}.
===Sebutan===
{{grc-IPA|πᾰνθᾰλής}}
===Kata sifat===
{{grc-adj-3rd|πανθαλές}}
# {{lb|grc|syair}} [[berbunga]], [[pemberi]] semua [[kemekaran]]
#*: {{Q|grc|Bacchylides|Odes|13|228-229|quote=τὰν εἰκ ἐτύμως ἄρα Κλειὼ<br>'''πανθαλὴς''' ἐμαῖς ἐνέσταξεν φρασίν {{...}} |trans=Dan jika ia<br>sesungguhnya telah '''berbunga''' [[w:Clio (muse)|Kleio]]<br>yang menerapkan [ia] di dalam hati saya {{...}} }}
====Infleksi====
{{grc-adecl|πανθαλής|πανθαλές}}
====Rujukan====
* {{R:LSJ}}
d8rcp7bax9mafj1mlqc4h8255dw2lgd
Modul:quote
828
13170
344389
253847
2026-05-26T03:53:08Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/90308046|90308046]])
344389
Scribunto
text/plain
--[=[
This module contains functions to implement quote-* templates.
Author: Benwing2; conversion into Lua of {{quote-meta/source}} template,
written by Sgconlaw with some help from Erutuon and Benwing2.
The main interface is quote_t(). Note that the source display is handled by source(), which reads both the
arguments passed to it *and* the arguments passed to the parent template, with the former overriding the latter.
]=]
local export = {}
--[=[
FIXME:
1. Dates like `1 march 2025` with the day of the month being 1 and the month lowercased are treated as month-year-only.
The relevant code checks for a capitalized word; it should probably instead check for the actual month names or
abbrevs.
]=]
-- Named constants for all modules used, to make it easier to swap out sandbox versions.
local check_isxn_module = "Module:check isxn"
local debug_track_module = "Module:debug/track"
local en_utilities_module = "Module:en-utilities"
local italics_module = "Module:italics"
local labels_module = "Module:labels"
local languages_module = "Module:languages"
local languages_error_module = "Module:languages/error"
local links_module = "Module:links"
local number_utilities_module = "Module:number utilities"
local parameters_module = "Module:parameters"
local parse_utilities_module = "Module:parse utilities"
local qualifier_module = "Module:qualifier"
local roman_numerals_module = "Module:roman numerals"
local scribunto_module = "Module:Scribunto"
local script_utilities_module = "Module:script utilities"
local scripts_module = "Module:scripts"
local string_pattern_escape_module = "Module:string/patternEscape"
local string_replacement_escape_module = "Module:string/replacementEscape"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local template_parser_module = "Module:template parser"
local usex_module = "Module:usex"
local usex_templates_module = "Module:usex/templates"
local utilities_module = "Module:utilities"
local yesno_module = "Module:yesno"
local concat = table.concat
local insert = table.insert
local new_title = mw.title.new
local remove = table.remove
local require = require
local sort = table.sort
local u = mw.ustring.char
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
-- Use HTML entities here to avoid parsing issues (esp. with brackets)
local SEMICOLON_SPACE = "; "
local SPACE_LBRAC = " ["
local RBRAC = "]"
local TEMP_LT = u(0xFFF1)
local TEMP_GT = u(0xFFF2)
local TEMP_LBRAC = u(0xFFF3)
local TEMP_RBRAC = u(0xFFF4)
local TEMP_SEMICOLON = u(0xFFF5)
local function apply_subst(...)
apply_subst = require(usex_module).apply_subst
return apply_subst(...)
end
local function check_isbn(...)
check_isbn = require(check_isxn_module).check_isbn
return check_isbn(...)
end
local function check_issn(...)
check_issn = require(check_isxn_module).check_issn
return check_issn(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function embedded_language_links(...)
embedded_language_links = require(links_module).embedded_language_links
return embedded_language_links(...)
end
local function escape_wikicode(...)
escape_wikicode = require(parse_utilities_module).escape_wikicode
return escape_wikicode(...)
end
local function find_best_script_without_lang(...)
find_best_script_without_lang = require(scripts_module).findBestScriptWithoutLang
return find_best_script_without_lang(...)
end
local function find_parameters(...)
find_parameters = require(template_parser_module).find_parameters
return find_parameters(...)
end
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
local function format_processed_labels(...)
format_processed_labels = require(labels_module).format_processed_labels
return format_processed_labels(...)
end
local function format_qualifier(...)
format_qualifier = require(qualifier_module).format_qualifier
return format_qualifier(...)
end
local function format_usex(...)
format_usex = require(usex_module).format_usex
return format_usex(...)
end
local function get_lang(...)
get_lang = require(languages_module).getByCode
return get_lang(...)
end
local function get_number(...)
get_number = require(number_utilities_module).get_number
return get_number(...)
end
local function get_script(...)
get_script = require(scripts_module).getByCode
return get_script(...)
end
local function gsplit(...)
gsplit = require(string_utilities_module).gsplit
return gsplit(...)
end
local function page_should_be_ignored(...)
page_should_be_ignored = require(usex_templates_module).page_should_be_ignored
return page_should_be_ignored(...)
end
local function parse_inline_modifiers(...)
parse_inline_modifiers = require(parse_utilities_module).parse_inline_modifiers
return parse_inline_modifiers(...)
end
local function parse_inline_modifiers_from_segments(...)
parse_inline_modifiers_from_segments = require(parse_utilities_module).parse_inline_modifiers_from_segments
return parse_inline_modifiers_from_segments(...)
end
local function parse_multi_delimiter_balanced_segment_run(...)
parse_multi_delimiter_balanced_segment_run = require(parse_utilities_module).parse_multi_delimiter_balanced_segment_run
return parse_multi_delimiter_balanced_segment_run(...)
end
local function parse_term_with_lang(...)
parse_term_with_lang = require(parse_utilities_module).parse_term_with_lang
return parse_term_with_lang(...)
end
local function pattern_escape(...)
pattern_escape = require(string_pattern_escape_module)
return pattern_escape(...)
end
local function pluralize(...)
pluralize = require(en_utilities_module).pluralize
return pluralize(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function remove_links(...)
remove_links = require(links_module).remove_links
return remove_links(...)
end
local function roman_to_arabic(...)
roman_to_arabic = require(roman_numerals_module).roman_to_arabic
return roman_to_arabic(...)
end
local function replacement_escape(...)
replacement_escape = require(string_replacement_escape_module)
return replacement_escape(...)
end
local function scribunto_parameter_key(...)
scribunto_parameter_key = require(scribunto_module).scribunto_parameter_key
return scribunto_parameter_key(...)
end
local function serial_comma_join(...)
serial_comma_join = require(table_module).serialCommaJoin
return serial_comma_join(...)
end
local function shallow_copy(...)
shallow_copy = require(table_module).shallowCopy
return shallow_copy(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function split_alternating_runs(...)
split_alternating_runs = require(parse_utilities_module).split_alternating_runs
return split_alternating_runs(...)
end
local function split_and_process_raw_labels(...)
split_and_process_raw_labels = require(labels_module).split_and_process_raw_labels
return split_and_process_raw_labels(...)
end
local function split_on_comma(...)
split_on_comma = require(parse_utilities_module).split_on_comma
return split_on_comma(...)
end
local function tag_text(...)
tag_text = require(script_utilities_module).tag_text
return tag_text(...)
end
local function tag_transcription(...)
tag_transcription = require(script_utilities_module).tag_transcription
return tag_transcription(...)
end
local function tag_translit(...)
tag_translit = require(script_utilities_module).tag_translit
return tag_translit(...)
end
local function ulen(...)
ulen = require(string_utilities_module).len
return ulen(...)
end
local function unitalicize_brackets(...)
unitalicize_brackets = require(italics_module).unitalicize_brackets
return unitalicize_brackets(...)
end
local function upper(...)
upper = require(string_utilities_module).upper
return upper(...)
end
local function usub(...)
usub = require(string_utilities_module).sub
return usub(...)
end
local function yesno(...)
yesno = require(yesno_module)
return yesno(...)
end
local function track(page)
debug_track("quote/" .. page)
end
local function maintenance_line(text)
return '<span class="maintenance-line">(' .. text .. ")</span>"
end
local function isbn(text)
return "[[Special:BookSources/"
.. text
.. "|→ISBN]]"
.. check_isbn(
text,
' <span class="error" style="font-size:88%">Invalid ISBN</span>[[Category:Pages with ISBN errors]]'
)
end
local function issn(text)
return "[https://www.worldcat.org/issn/"
.. text
.. " →ISSN]"
.. check_issn(
text,
' <span class="error" style="font-size:88%">Invalid ISSN</span>[[Category:Pages with ISSN errors]]'
)
end
local function lccn(text)
text = text:gsub(" ", "")
if text:find("-") then
-- old-style LCCN; reformat per request by [[User:The Editor's Apprentice]]
local prefix, part1, part2 = text:match("^(.-)(%d+)%-(%d+)$")
if prefix then
if ulen(part2) < 6 then
part2 = ("0"):rep(6 - ulen(part2)) .. part2
end
text = prefix .. part1 .. part2
end
end
return "[https://lccn.loc.gov/" .. mw.uri.encode(text) .. " →LCCN]"
end
local function format_date(text)
return mw.getCurrentFrame():callParserFunction("#formatdate", text, "dmy")
end
-- Parse a raw lb= param (or nil) to individual label info objects and then concatenate them appropriately into a
-- qualifier input, respecting flags like `omit_preComma` and `omit_postSpace` in the label specs.
local function parse_and_format_labels(raw_lb, lang)
if not raw_lb then
return nil
end
local labels = split_and_process_raw_labels{labels = raw_lb, lang = lang, nocat = true}
labels = format_processed_labels{labels = labels, lang = lang, no_ib_content = true}
if labels ~= "" then -- not sure labels can be an empty string but it seems possible in some circumstances
return {labels}
end
end
-- Convert a comma-separated list of language codes to a comma-separated list of language names. `fullname` is the
-- name of the parameter from which the list of language codes was fetched.
local function format_langs(langs)
local names = {}
for i, lang in ipairs(langs) do
names[i] = lang:getCanonicalName()
end
if #names == 1 then
return names[1]
end
return serial_comma_join(names)
end
local function get_first_lang(langs)
return langs[1] or get_lang("und")
end
--[=[
Normally we parse off inline modifiers and language code prefixes in various places, e.g. he:מרים<tr:Miryem>. But we
exclude HTML entries with <span ...>, <i ...>, <br/> or similar in it, caused by wrapping an argument in {{l|...}},
{{lang|...}} or similar. Basically, all tags of the sort we parse here should consist of a less-than sign, plus letters,
plus a colon, e.g. <tr:...>, so if we see a tag on the outer level that isn't in this format, we don't try to parse it.
The restriction to the outer level is to allow generated HTML inside of e.g. qualifier modifiers, such as
foo<q:similar to {{m|fr|bar}}> (if we end up supporting such modifiers).
Also exclude things that look like URL's from being parsed as having language code prefixes.
]=]
local function val_should_not_be_parsed_for_annotations(val)
return val:find("^[^<]*<%l*[^%l:]") or val:find("^%l+://")
end
local param_mods = {
t = {
-- <t:...> and <gloss:...> are aliases.
item_dest = "gloss",
},
gloss = {},
alt = {},
tr = {},
ts = {},
subst = {},
sc = {type = "script"},
f = {
convert = function(arg, parse_err)
local prefix, val = arg:match("^(.-):([^ ].*)$")
if not prefix then
prefix = ""
val = arg
end
local tags, sc_code, sc = prefix:match("^(.*)/(.-)$")
if sc_code then
sc = get_script(sc_code) or
require(languages_error_module)(sc_code, parse_err, "script code", nil, "not real lang")
else
tags = prefix
end
local quals
if tags ~= "" then
quals = split_on_comma(tags)
for i, qual in ipairs(quals) do
local obj = get_lang(qual, nil, "allow etym") or get_script(qual)
quals[i] = obj or qual
end
end
return {
quals = quals,
sc = sc,
val = val,
}
end,
store = "insert",
},
q = {},
qq = {},
}
local function generate_obj_annotated_text(text, parse_err, paramname)
local obj = {}
if text:find(":[^ ]") or text:find("%[%[") then
local display, is_wikipedia_wikisource
obj.text, obj.lang, obj.link, display, is_wikipedia_wikisource =
parse_term_with_lang {
term = text,
parse_err = parse_err,
paramname = paramname
}
-- HACK: If object is a Wikipedia or Wikisource link, we need to convert it to a two-part link
-- to avoid the w: or s: prefix showing. We should probably avoid this by calling
-- language_link() (in [[Module:links]]) in format_annotated_text() instead of the hacky stuff
-- that we currently do; but we need to test that carefully to make sure it doesn't do things like
-- munge % signs.
if is_wikipedia_wikisource and not obj.text:find("%[%[") and not obj.text:find("%]%]") then
-- Don't directly set .alt, because then if the user specifies <alt:...>, it will cause an error in
-- parse_inline_modifiers().
obj.display = display
end
else
obj.text = text
obj.link = text
end
return obj
end
--[=[
Parse a textual property that may be in a foreign language or script and may be annotated with a language prefix and/or
inline modifiers. `val` is the value of the parameter and `fullname` is the name of the parameter from which the value
was retrieved. `explicit_gloss`, if specified and non-nil, overrides any gloss specified using the <t:...> or
<gloss:...> inline modifier.
If `val` is nil, the return value of this function is nil. Otherwise it is parsed for a language prefix (e.g.
'ar:مُؤَلِّف') and inline modifiers (e.g. 'ar:مُؤَلِّف<t:Author>'), and the return value is an object with the following
fields:
`lang`: The language object corresponding to the language prefix, if specified, or nil if no language prefix is
given.
`text`: The text after stripping off any language prefix and inline modifiers.
`link`: The link part of the text if it consists of a two-part link; otherwise, same as `text`.
`alt`: Display text specified using the <alt:...> modifier, if given; otherwise, nil.
`subst`: Substitutions used to generate the transliteration, in the same format as the subst= parameter.
`sc`: The script object corresponding to the <sc:...> modifier, if given; otherwise nil.
`tr`: The transliteration corresponding to the <tr:...> modifier, if given; otherwise nil.
`ts`: The transcription corresponding to the <ts:...> modifier, if given; otherwise nil.
`gloss`: The gloss/translation corresponding to the `explicit_gloss` parameter (if given and non-nil), otherwise
the <t:...> or <gloss:...> modifiers if given, otherwise nil.
`f`: Foreign versions of the text.
`q`: Left qualifiers.
`qq`: Right qualifiers.
Note that as a special case, if `val` contains HTML tags at the top level (e.g. '<span class="Arab">...</span>', as
might be generated by specifying {{lang|ar|مُؤَلِّف}}), no language prefix or inline modifiers are parsed, and the return
value has the `noscript` field set to true, which tells format_annotated_text() not to try to identify the script of
the text and CSS-tag the text accordingly, but to leave the text untagged.
This object can be passed to format_annotated_text() to format a string displaying the text (appropriately
script-tagged, unless `noscript` is set, as described above) and modifiers.
]=]
local function parse_annotated_text(val, fullname, explicit_gloss)
if not val then
return nil
end
-- When checking for inline modifiers, exclude HTML entry with <span ...>, <i ...>, <br/> or similar in it, caused
-- by wrapping an argument in {{l|...}}, {{lang|...}} or similar. Also exclude URL's from being parsed as having
-- language code prefixes. See val_should_not_be_parsed_for_annotations() for more information. If we find a
-- parameter value with top-level HTML in it, add 'noscript = true' to indicate that we should not try to do script
-- inference and tagging. (Otherwise, e.g. if you specify {{lang|ar|مُؤَلِّف}} as the author, you'll get an extra big
-- font coming from the fact that {{lang|...}} wraps the Arabic text in CSS that increases the size from the
-- default, and then we do script detection and again wrap the text in the same CSS, which increases the size even
-- more.)
if val_should_not_be_parsed_for_annotations(val) then
return {text = val, link = val, noscript = true, gloss = explicit_gloss}
end
local obj
if val:find("<") then
-- Check for inline modifier.
obj = parse_inline_modifiers(val, {
paramname = fullname,
param_mods = param_mods,
generate_obj = generate_obj_annotated_text,
})
else
obj = generate_obj_annotated_text(val, nil, fullname)
end
if explicit_gloss then
obj.gloss = explicit_gloss
end
return obj
end
local html_entity_char_to_replacement = {
["<"] = TEMP_LT,
[">"] = TEMP_GT,
["["] = TEMP_LBRAC,
["]"] = TEMP_RBRAC,
}
local function html_entity_replacement(entity, code_without_semicolon, hash, xcode, x, code)
-- Try to decode the entity. If successful, Replace certain special HTML entities (those that are bracket-like)
-- with single Unicode characters; otherwise, replace the semicolon with a special character so it won't get
-- interpreted as a delimiter.
local ch = decode_entities(entity)
if ch ~= entity then
return html_entity_char_to_replacement[ch] or code_without_semicolon .. TEMP_SEMICOLON
end
-- If the entity doesn't decode, escape it anyway iff it follows a valid format.
if hash == "" then
-- Any nonstandard MediaWiki-only entities have now been filtered off, so treat any non-ASCII characters as
-- invalid.
return xcode:match("^[^\128-\255]+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
elseif x == "" then
return xcode:match("^%d+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
end
return code:match("^%x+$") and code_without_semicolon .. TEMP_SEMICOLON or entity
end
local html_entity_replacement_to_char = {
[TEMP_LT] = "<",
[TEMP_GT] = ">",
[TEMP_LBRAC] = "[",
[TEMP_RBRAC] = "]",
[TEMP_SEMICOLON] = ";",
}
local function undo_html_entity_replacement(txt)
-- Pattern covers everything in html_entity_replacement_to_char.
return (txt:gsub("\239\191[\177-\181]", html_entity_replacement_to_char))
end
-- NOTE: We try hard to optimize this function for the common cases and avoid loading [[Module:parse utilities]]
-- in such cases. The cases we can handle without loading [[Module:parse utilities]] are single values (no
-- semicolons present) without inline modifiers or language prefixes, and multi-entity values (semicolons present)
-- without (a) brackets of any kind (including parens, braces and angle brackets; angle brackets typically indicate
-- inline modifiers and other brackets may protect a semicolon from being interpreted as a delimiter);
-- (b) ampersands (which may indicate HTML entities, which protect a semicolon from being interpreted as a
-- delimiter); and (c) colons not followed by a space (which may indicate a language prefix).
local function generate_obj_multivalued_annotated_text(text, parse_err, paramname, no_undo_html_entity_replacement)
local obj = generate_obj_annotated_text(text, parse_err, paramname)
if not no_undo_html_entity_replacement then
obj.text = undo_html_entity_replacement(obj.text)
obj.link = undo_html_entity_replacement(obj.link)
end
return obj
end
--[=[
Similar to parse_annotated_text() but the parameter value may contain multiple semicolon-separated entities, each with
their own inline modifiers. Some examples:
* mainauthor=Paula Pattengale; Terea Sonsthagen
* author=Katie Brick; J. Cody Nielsen; Greg Jao; Eric Paul Rogers; John A. Monson
* author=Suzanne Brockmann; Patrick G. Lawlor (Patrick Girard); Melanie Ewbank
* author=G Ristori; et al.
* author=Jason Scott; zh:王晰宁<t:Wang Xining>
* editors=zh:包文俊; zh:金心雯
* quotee=zh:張福運<t:Chang Fu-yun>; zh:張景文<t:Chang Ching-wen>
There may be embedded semicolons within brackets, braces or parens that should not be treated as delimiters, e.g.:
* author=Oliver Optic [pseudonym; {{w|William Taylor Adams}}]
* author=author=Shannon Drake (pen name; {{w|Heather Graham Pozzessere}})
* author=James (the Elder;) Humphrys
There may also be HTML entities with semicolons in them:
* author=[{{w|Gilbert Clerke}}]
* 2ndauthor=Martin Biddle & Sally Badham
* author=Peter Christen Asbjørnsen
There may be both embedded semicolons and HTML entities with semicolons in them:
* author=[{{w|Voltaire}} [pseudonym; François-Marie Arouet]]
In general we want to treat [ like an opening bracket and ] like a closing bracket. Beware that they may be
mismatched:
* author=Anonymous [{{w|Karl Maria Kertbeny}}]
Here, `val` is the value of the parameter and `fullname` is the name of the parameter from which the value was
retrieved. `explicit_gloss`, if specified and non-nil, overrides any gloss specified using the <t:...> or <gloss:...>
inline modifier, and `explicit_gloss_fullname` is the name of the parameter from which this value was retrieved. (If
`explicit_gloss` is specified and multiple values were seen, an error results.)
Return value is a list of objects of the same sort as returned by parse_annotated_text().
]=]
local function parse_multivalued_annotated_text(val, fullname, explicit_gloss, explicit_gloss_fullname)
if not val then
return nil
end
-- NOTE: In the code that follows, we use `entity` most of the time to refer to one of the semicolon-separated
-- values in the multivalued param. Entities are most commonly people (typically authors, editors, translators or
-- the like), but may be the names of publishers, locations, or other entities. "Entity" can also refer to HTML
-- entities; in the places where this occurs, the variable name contains 'html' in it.
local splitchar, english_delim
if val:find("^,") then
splitchar = ","
english_delim = "comma"
val = val:gsub("^,", "")
else
splitchar = ";"
english_delim = "semicolon"
end
-- Optimization #1: No semicolons/commas or angle brackets (indicating inline modifiers).
if not val:find("[<" .. splitchar .. "]") then
if val_should_not_be_parsed_for_annotations(val) then
return {{text = val, link = val, noscript = true}}
else
return {generate_obj_multivalued_annotated_text(val, nil, fullname, "no undo html entity replacement")}
end
end
-- Optimization #2: Semicolons/commas but no angle brackets (indicating inline modifiers), braces, brackets, or
-- parens (any of which would protect the semicolon/comma from interpretation as a delimiter), and no ampersand
-- (which might indicate an HTML entity with a terminating semicolon, which should not be interpreted as a
-- delimiter).
if not val:find("[<>%[%](){}&]") then
local entity_objs = {}
for entity in gsplit(val, "%s*" .. splitchar .. "%s*") do
if val_should_not_be_parsed_for_annotations(entity) then
insert(entity_objs, {
text = entity,
link = entity,
noscript = true
})
else
insert(entity_objs, generate_obj_multivalued_annotated_text(entity, nil, fullname, "no undo html entity replacement"))
end
end
return entity_objs
end
-- Escape HTML entities, and get rid of directionality markers.
local amp = val:find("&", nil, true)
if amp then
-- The pattern is more permissive than the usual entity pattern, as MediaWiki has some nonstandard entities
-- that have non-ASCII characters in their codes.
val = val:gsub("((&(#?)(([xX]?)([%w\128-\255]+)));)", html_entity_replacement)
end
-- Pattern covers left-to-right (U+200E) and right-to-left (U+200F).
val = val:gsub("\226\128[\142\143]", "")
-- Parse balanced segment runs, treating HTML entities for left and right bracket and left and right angle bracket
-- as matching literal versions of the same characters.
local entity_runs = parse_multi_delimiter_balanced_segment_run(
val,
{{"[" .. TEMP_LBRAC, "]" .. TEMP_RBRAC}, {"(", ")"}, {"{", "}"}, {"<" .. TEMP_LT, ">" .. TEMP_GT}},
true
)
if type(entity_runs) == "string" then
local undo_val = undo_html_entity_replacement(val)
-- Parse error due to unbalanced delimiters. Don't throw an error here; instead, don't attempt to parse off
-- any annotations, but return the value directly, maybe allowing script tagging (not allowing it if it appears
-- the text is already script-tagged).
return {{text = undo_val, link = undo_val, noscript = not not val_should_not_be_parsed_for_annotations(val)}}
end
-- Split on semicolon (or comma), possibly surrounded by whitespace.
local separated_groups = split_alternating_runs(entity_runs, "%s*" .. splitchar .. "%s*")
-- Process each value.
local entity_objs = {}
for _, entity_group in ipairs(separated_groups) do
-- Rejoin runs that don't involve <...>.
local j = 2
while j <= #entity_group do
if not entity_group[j]:find("^<.*>$") then
entity_group[j - 1] = entity_group[j - 1] .. entity_group[j] .. entity_group[j + 1]
remove(entity_group, j)
remove(entity_group, j)
else
j = j + 2
end
end
local oneval = undo_html_entity_replacement(concat(entity_group))
-- When checking for inline modifiers, exclude HTML entry with <span ...>, <i ...>, <br/> or similar in it,
-- caused by wrapping an argument in {{l|...}}, {{lang|...}} or similar. Also exclude URL's from being parsed
-- as having language code prefixes. This works analogously to parse_annotated_text(); see there for more.
if val_should_not_be_parsed_for_annotations(oneval) then
insert(entity_objs, {
text = oneval,
link = oneval,
noscript = true
})
else
local obj
if #entity_group > 1 then
-- Check for inline modifier.
obj = parse_inline_modifiers_from_segments({
group = entity_group,
arg = oneval,
props = {
paramname = fullname,
param_mods = param_mods,
generate_obj = generate_obj_multivalued_annotated_text,
},
})
else
obj = generate_obj_multivalued_annotated_text(entity_group[1], nil, fullname)
end
insert(entity_objs, obj)
end
end
if explicit_gloss then
if #entity_objs > 1 then
error(
(
"Can't specify |%s= along with multiple %s-separated entities in |%s=; use the <t:...> "
.. "inline modifier attached to the individual entities"
):format(explicit_gloss_fullname, english_delim, fullname)
)
end
entity_objs[1].gloss = explicit_gloss
end
return entity_objs
end
--[=[
Format a text property that may be in a foreign language or script, along with annotations. This is conceptually
similar to the full_link() function in [[Module:links]], but displays the annotations in a different format that is
more appropriate for bibliographic entries. The output looks like this:
TEXT [TRANSLIT /TRANSCRIPTION/, GLOSS]
`textobj` is as returned by parse_annotated_text(). `tag_text_func`, if supplied, is a function of one argument to further
wrap the text after it has been processed and CSS-tagged appropriately, directly before insertion. `tag_gloss_func` is a
similar function for the gloss.
]=]
local function format_annotated_text(textobj, tag_text_func, tag_gloss_func)
if not textobj then
return nil
end
local text, link = textobj.text, textobj.link
local subst, tr, ts, f, gloss = textobj.subst, textobj.tr, textobj.ts, textobj.f, textobj.gloss
-- Retrieve the display text, either specified by the user (.alt) or by parse_annotated_text() (.display) when a
-- Wikipedia link is given.
local alt = textobj.alt or textobj.display
if alt then
if link:find("%[%[") or link:find("%]%]") then
local errmsg = ("Can't currently handle embedded links in '%s', with <alt:...> text '%s'"):format(link, alt)
error(escape_wikicode(errmsg))
end
text = ("[[%s|%s]]"):format(link, alt)
end
-- See above for `noscript`, meaning HTML was found in the text value, probably generated using {{lang|...}}.
-- {{lang}} already script-tags the text and processes embedded language links, so we don't want to do it again (in
-- fact, the code below within the if-clause is similar to what {{lang}} does). In such a case, an explicit language
-- won't be available and find_best_script_without_lang() may not be accurate, so we can't do automatic transliteration.
if not textobj.noscript then
local lang = textobj.lang
-- As an optimization, don't do script detection on an argument that contains only ASCII.
local sc = textobj.sc
or lang and lang:findBestScript(text)
or not text:find("^[ -~]$") and find_best_script_without_lang(text)
or nil
-- As an optimization, don't do any of the following if there's no language, script, translit or transcription,
-- as will be the case with simple ASCII values.
if lang or sc or tr or ts then
if not lang then
lang = get_lang("und")
end
if tr == "-" then
tr = nil
elseif not tr and sc and not sc:getCode():find("Lat") then -- Latn, Latf, Latg, pjt-Latn
-- might return nil
local text_for_tr = text
if subst then
text_for_tr = apply_subst(text_for_tr, subst)
else
text_for_tr = remove_links(text)
end
tr = (lang:transliterate(text_for_tr, sc))
end
if text:find("%[%[") then
-- FIXME: embedded_language_links() replaces % signs with their URL-encoded equivalents,
-- which messes up URL's that may be present (e.g. if chapterurl= is given). IMO this
-- should not happen, and embedded_language_links() should do nothing if no embedded links
-- are present. To work around this, only call embedded_language_links() when there are
-- embedded links present.
text = embedded_language_links({
term = text,
lang = lang,
sc = sc,
})
end
if lang:getCode() ~= "und" or sc:getCode() ~= "Latn" then
text = tag_text(text, lang, sc)
end
if tr then
-- Should we link to the transliteration of languages with lang:link_tr()? Probably not because `text` is not
-- likely to be a term that has an entry.
tr = tag_translit(tr, lang, "usex")
end
if ts then
ts = tag_transcription(ts, lang, "usex")
end
end
end
text = unitalicize_brackets(text)
if tag_text_func then
text = tag_text_func(text)
end
local parts = {}
if textobj.q then
insert(parts, format_qualifier(textobj.q) .. " ")
end
insert(parts, text)
if tr or ts or f or gloss then
insert(parts, SPACE_LBRAC)
local subparts = {}
if tr or ts then
local tr_ts
if ts then
ts = "/" .. ts .. "/"
end
if tr and ts then
tr_ts = tr .. " " .. ts
else
tr_ts = tr or ts
end
insert(subparts, tr_ts)
end
if f then
for _, ff in ipairs(f) do
local sc = ff.sc
local lang
if not sc and ff.quals then
local qual = ff.quals[1]
if type(qual) == "string" then
-- do nothing; we'll do script detection farther down
elseif qual:hasType("script") then
sc = qual
else -- language
sc = qual:findBestScript(ff.val)
lang = qual
end
end
if not lang then
lang = get_lang("und")
end
sc = sc or find_best_script_without_lang(ff.val)
local val = embedded_language_links({
term = ff.val,
lang = lang,
sc = sc,
})
if lang:getCode() ~= "und" or sc:getCode() ~= "Latn" then
val = tag_text(val, lang, sc)
end
local qual_prefix
if ff.quals then
for i, qual in ipairs(ff.quals) do
if type(qual) ~= "string" and (qual:hasType("script") or qual:hasType("language")) then
ff.quals[i] = qual:getCanonicalName()
end
end
qual_prefix = concat(ff.quals, "/") .. ": "
else
qual_prefix = ""
end
insert(subparts, qual_prefix .. val)
end
end
if gloss then
gloss = '<span class="e-translation">' .. gloss .. "</span>"
gloss = unitalicize_brackets(gloss)
if tag_gloss_func then
gloss = tag_gloss_func(gloss)
end
insert(subparts, gloss)
end
insert(parts, concat(subparts, ", "))
insert(parts, RBRAC)
end
if textobj.qq then
insert(parts, " " .. format_qualifier(textobj.qq))
end
return concat(parts)
end
--[=[
Format a multivalued text property that may be in a foreign language or script, along with annotations. This is the
multivalued analog to format_annotated_text(), and formats each individual entity using format_annotated_text(),
joining the results with `delimiter`, which defaults to ", ". It `delimiter` is "and" or "or", join the results using
serial_comma_join() with the specified conjunction.
`textobjs` is as returned by parse_multivalued_annotated_text(). `tag_text_func` and `tag_gloss_func` are as in
format_annotated_text().
]=]
local function format_multivalued_annotated_text(textobjs, delimiter, tag_text_func, tag_gloss_func)
if not textobjs then
return nil
end
if #textobjs == 1 then
return format_annotated_text(textobjs[1], tag_text_func, tag_gloss_func)
end
local parts = {}
for _, textobj in ipairs(textobjs) do
insert(parts, format_annotated_text(textobj, tag_text_func, tag_gloss_func))
end
-- Change delimiter to semicolon if the items themselves contain commas (e.g., in ", Jr.")
local use_semicolon = false
for _, obj in ipairs(textobjs) do
-- Use remove_links to ignore commas in links
if obj.text and remove_links(obj.text):find(", ") then
use_semicolon = true
break
end
end
local n = #parts
if n > 0 and parts[n]:match("^'*et al[.']*$") then
-- Special handling for 'et al.'
parts[n] = "''et al.''"
if n == 2 then
-- author et al.
return concat(parts, " ")
else
-- author 1, author 2, et al.
return concat(parts, (use_semicolon and "; ") or ", ")
end
if delimiter == "and" or delimiter == "or" then
delimiter = ", "
end
return concat(parts, delimiter)
end
if delimiter == "and" or delimiter == "or" then
return serial_comma_join(parts, {conj = delimiter})
end
return concat(parts, delimiter or ((use_semicolon and "; ") or ", "))
end
-- Fancy version of ine() (if-not-empty). Converts empty string to nil, but also strips leading/trailing space.
local function ine(arg)
if not arg then
return nil
elseif type(arg) ~= "string" then
return arg
end
arg = mw.text.trim(arg)
if arg == "" then
return nil
end
return arg
end
local abbrs = {
["a."] = {anchor = "a.", full = "ante"},
["c."] = {anchor = "c.", full = "circa"},
["p."] = {anchor = "p.", full = "post"},
}
-- Process prefixes 'a.' (ante), 'c.' (circa) and 'p.' (post) at the beginning of an arbitrary date or year spec.
-- Returns two values, the formatted version of the prefix and the date spec minus the prefix. If no prefix is found,
-- returns an empty string and the full date.
local function process_ante_circa_post(date)
local prefix = usub(date, 1, 2)
local abbr = abbrs[prefix]
local abbr_prefix = ""
if abbr then
abbr_prefix = "''[[Appendix:Glossary#"
.. abbr.anchor
.. '|<abbr title="'
.. abbr.full
.. '">'
.. abbr.anchor
.. "</abbr>]]'' "
-- Remove lowercase letter, period, and space from beginning of date parameter.
date = ugsub(date, "^%l%.%s*", "")
end
return abbr_prefix, date
end
-- Format the arguments that specify the date of the quotation. These include the following:
-- |date=: The date. If |start_date= is given, this is the end date.
-- |year=, |month=: Year and month of quotation date or end of range, if |date= isn't given.
-- |start_date=: The start date, to specify a range.
-- |start_year=, |start_month=: Year and month of start of range, if |start_date= isn't given.
-- |accessdate=: Date a website was accessed; processed if no other date was given.
-- |nodate=: Indicate that no date is present; otherwise a maintenance line will be displayed if there is no date.
--
-- If `parampref` and/or `paramsuf` are given, this modifies all the date arguments accordingly. For example, if
-- `parampref` == "orig" and `paramsuf` is omitted, the date is specified using |origdate= or |origyear=/|origmonth=,
-- and the start of the range is |origstart_date=, etc. Similarly, if `parampref` is omitted and `paramsuf` is
-- "_published", the date is specified using |date_published= or |year_published=/|month_published=, and the start of
-- the range is |start_date_published=, etc.
--
-- `a` and `get_full_paramname` are functions with the same interpretation as the local functions of the same name in
-- source(). These are used to fetch parameters and get their full names. Note that this may cause all arguments to
-- have an index added to them (|date2=, |year2=, |month2=, etc.).
--
-- `alias_map` is as in source() and is used to map canonical arguments to their aliases when aliases were used.
--
-- If `bold_year` is given, displayed years are boldfaced unless boldface is present in the parameter value.
--
-- If `maintenance_line_no_date` is specified, it should be a string that will be returned if no date is found (i.e.
-- neither |date= nor |year=, or their appropriate equivalents per `parampref` and `paramsuf`, are specified, and
-- neither |nodate= is given to indicate that there is no date, or |accessdate= is given).
--
-- Returns two values: the formatted date and a boolean indicating whether to add a maintenance category
-- [[:Category:Requests for date in LANG entries]]. The first return value will be nil if nothing is to be added
-- (in which case the scond return value will always be nil).
local function format_date_args(
a,
get_full_paramname,
alias_map,
parampref,
paramsuf,
bold_year,
maintenance_line_no_date,
year_last
)
local output = {}
parampref = parampref or ""
paramsuf = paramsuf or ""
local function getp(param)
return a(parampref .. param .. paramsuf)
end
local function pname(param)
local fullname = get_full_paramname(parampref .. param .. paramsuf)
return alias_map[fullname] or fullname
end
-- Format `timestamp` (a timestamp referencing a date) according to the spec in `code`. `param` is the base name of
-- the parameter from which the timestamp was fetched, for error messages.
local function format_date_with_code(code, timestamp, param)
local language = mw.getContentLanguage()
local ok, date = pcall(language.formatDate, language, code, timestamp)
if ok then
return date
else
-- All the formats used in format_date_args() are fine, so the timestamp must be at fault.
error(
(
"Timestamp |%s=%s (possibly canonicalized from its original format) could not be parsed; see the "
.. "[[mw:Help:Extension:ParserFunctions##time|documentation for the #time parser function]]"
):format(pname(param), tostring(timestamp))
)
end
end
-- Try to figure out if the given timestamp has the day of the month explicitly given. We use the following
-- algorithm:
-- 1. Format as year-month-day; if the day is not 1, the day was explicitly given, since if only the year/month are
-- given, the day shows up as 1.
-- 2. If the day shows up as 1 and there isn't a 1 or 01 in the timestamp, the day wasn't explicitly given.
-- 3. Otherwise, if there are three separate numbers (e.g. 2022-07-01), or two separate numbers plus a capitalized
-- letter (taken as an English month, e.g. 2022 July 1), the day was explicitly given, otherwise not.
--
-- `param` is the base name of the parameter from which the timestamp was fetched.
local function date_has_day_specified(timestamp, param)
local day = format_date_with_code("j", timestamp, param)
if day ~= "1" then
return true
end
local english_month = timestamp:find("%u")
local canon_timestamp = mw.text.trim((timestamp:gsub("%D+", " ")))
local seen_nums = split(canon_timestamp, " ", true)
local saw_one = false
for _, num in ipairs(seen_nums) do
if num == "1" or num == "01" then
saw_one = true
break
end
end
if not saw_one then
return false
end
return #seen_nums >= 3 or english_month and #seen_nums >= 2
end
-- Format a date with boldfaced year, as e.g. '''2023''' August 3. `explicit_day_given` indicates whether to include
-- the day; if false, the return value will be e.g. '''2023''' August. `date_param` is the base name of the param
-- from which the date was fetched, for error messages.
local function format_bold_date(date, explicit_day_given, date_param)
local day_month_code = explicit_day_given and "j F" or "F"
local month_day_code = explicit_day_given and "F j" or "F"
if year_last then
if bold_year then
-- This formats like "3 August '''2023'''" (or "August '''2023'''" if day not explicitly given).
return format_date_with_code(day_month_code .. " '''Y'''", date, date_param)
else
-- This formats like "3 August 2023" (or "August 2023" if day not explicitly given).
return format_date_with_code(day_month_code .. " Y", date, date_param)
end
else
if bold_year then
-- This formats like "'''2023''' August 3" (or "'''2023''' August" if day not explicitly given).
return format_date_with_code("'''Y''' " .. month_day_code, date, date_param)
else
-- This formats like "2023 August 3" (or "2023 August" if day not explicitly given).
return format_date_with_code("Y " .. month_day_code, date, date_param)
end
end
end
-- The formatDate method of the mw.language object behaves like the {{#time:}} parser function, which doesn't
-- accept the formats "monthday monthname, year" or "year monthname monthday", but outputs garbage when it receives
-- them, behavior inherited from PHP. {{#formatdate:}} magic word is more forgiving. Fix dates so that, for
-- instance, the |date= parameter of {{quote-journal}} (which uses this code) and the |accessdate= parameter (which
-- uses {{#formatdate:}}) accept similar date formats. See:
-- * [[mw:Extension:Scribunto/Lua_reference_manual#mw.language:formatDate]]
-- * [[mw:Help:Extension:ParserFunctions##time]]
-- * [[mw:Help:Magic_words#Formatting]]
-- `date` is the date spec from the user, which is assumed to come from a parameter whose base name ends in "date";
-- `parampref` is the prefix added to "date" to get the parameter name.
local function fix_date(date, param_pref)
if tonumber(date) ~= nil then
error(
("|%s= should contain a full date (year, month, day of month); use |%s= for year"):format(
pname(param_pref .. "date"),
pname(param_pref .. "year")
)
)
elseif date and date:find("%s*%a+,%s*%d+%s*$") then
error(
("|%s= should contain a full date (year, month, day of month); use |%s=, |%s= for month and year"):format(
pname(param_pref .. "date"),
pname(param_pref .. "month"),
pname(param_pref .. "year")
)
)
end
if date then
-- Commas are replaced with spaces to prevent parsing issues
local fixed_date = ugsub(date, ", *", " ")
return (ugsub(ugsub(fixed_date or date, "(%d+ %a+),", "%1"), "^(%d%d%d%d) (%a+ %d%d?)$", "%2 %1"))
end
end
local start_date, date = fix_date(getp("start_date"), "start_"), fix_date(getp("date"), "")
local year = getp("year")
local month = getp("month")
local start_year = getp("start_year")
local start_month = getp("start_month")
if date and year then
error(("Only one of |%s= or |%s= should be specified"):format(pname("date"), pname("year")))
end
if date and month then
error(
("|%s= should only be specified in conjunction with |%s=, not with |%s="):format(
pname("month"),
pname("year"),
pname("date")
)
)
end
if start_date and start_year then
error(("Only one of |%s= or |%s= should be specified"):format(pname("start_date"), pname("start_year")))
end
if start_date and start_month then
error(
("|%s= should only be specified in conjunction with |%s=, not with |%s="):format(
pname("start_month"),
pname("start_year"),
pname("start_date")
)
)
end
if (start_date or start_year) and not (date or year) then
error(
("|%s= or |%s=/|%s= cannot be specified without specifying |%s= or |%s=/|%s="):format(
pname("start_date"),
pname("start_year"),
pname("start_month"),
pname("date"),
pname("year"),
pname("month")
)
)
end
local dash = " – "
local day_explicitly_given = date and date_has_day_specified(date, "date")
local start_day_explicitly_given = start_date and date_has_day_specified(start_date, "start_date")
-- Format a date with boldfaced year, as e.g. '''2023''' August 3 (if `explicit_day_given` specified) or
-- '''2023''' August (if `explicit_day_given` not specified). If no date specified, fall back to formatting based
-- on the year and (optionally) month params given in `yearobj` and `monthobj`, boldfacing the year if not already.
-- `date_param` is the base name of the param from which the date was fetched, for error messages.
local function format_date_or_year_month(date, yearobj, monthobj, explicit_day_given, date_param)
if date then
return format_bold_date(date, explicit_day_given, date_param)
else
-- Boldface a year spec if it's not already boldface.
if bold_year and not yearobj.text:find("'''") then
-- Clone the year object before modifying it because we may use it later to check against the current
-- year (if we're dealing with start_year).
yearobj = shallow_copy(yearobj)
yearobj.text = "'''" .. yearobj.text .. "'''"
if yearobj.alt then
yearobj.alt = "'''" .. yearobj.alt .. "'''"
end
end
if year_last then
return (monthobj and format_annotated_text(monthobj) .. " " or "") .. format_annotated_text(yearobj)
else
return format_annotated_text(yearobj) .. (monthobj and " " .. format_annotated_text(monthobj) or "")
end
end
end
local yearobj = parse_annotated_text(year, pname("year"))
local monthobj = parse_annotated_text(month, pname("month"))
local start_yearobj = parse_annotated_text(start_year, pname("start_year"))
local start_monthobj = parse_annotated_text(start_month, pname("start_month"))
if start_yearobj then
local abbr_prefix
abbr_prefix, start_yearobj.text = process_ante_circa_post(start_yearobj.text)
start_yearobj.link = select(2, process_ante_circa_post(start_yearobj.link))
insert(output, abbr_prefix)
elseif yearobj then
local abbr_prefix
abbr_prefix, yearobj.text = process_ante_circa_post(yearobj.text)
yearobj.link = select(2, process_ante_circa_post(yearobj.link))
insert(output, abbr_prefix)
end
if start_date or start_year then
local cur_year = yearobj and yearobj.text or format_date_with_code("Y", date, "date")
local cur_month = monthobj and monthobj.text or date and format_date_with_code("F", date, "date") or nil
local cur_day = date and day_explicitly_given and format_date_with_code("j", date, "date") or nil
local beg_year = start_yearobj and start_yearobj.text or format_date_with_code("Y", start_date, "start_date")
local beg_month = start_monthobj and start_monthobj.text
or start_date and format_date_with_code("F", start_date, "start_date")
or nil
local beg_day = start_date
and start_day_explicitly_given
and format_date_with_code("j", start_date, "start_date")
or nil
if year_last then
if beg_day then
insert(output, beg_day .. " " .. beg_month)
else
insert(output, beg_month)
end
if beg_year ~= cur_year then
insert(output, " " .. beg_year)
end
else
insert(output, format_date_or_year_month(
start_date,
start_yearobj,
start_monthobj,
start_day_explicitly_given,
"start_date"
))
end
if cur_year ~= beg_year then
-- Different years; insert current date in full.
if beg_month or cur_month then
insert(output, dash)
else
insert(output, "–")
end
insert(output, format_date_or_year_month(date, yearobj, monthobj, day_explicitly_given, "date"))
elseif cur_month and cur_month ~= beg_month then
local month_ins = monthobj and format_annotated_text(monthobj) or cur_month
-- Same year but different months; insert current month and (if available) current day.
if cur_day then
insert(output, dash)
if year_last then
insert(output, cur_day .. " " .. month_ins)
else
insert(output, month_ins .. " " .. cur_day)
end
else
if beg_day then
insert(output, dash)
else
insert(output, "–")
end
insert(output, month_ins)
end
elseif cur_day and cur_day ~= beg_day then
-- Same year and month but different days; insert current day.
insert(output, "–")
insert(output, cur_day)
else
-- Same year, month and day; or same year and month, and day not available; or same year, and month and
-- day not available. Do nothing. FIXME: Should we throw an error?
end
if year_last and beg_year == cur_year then
if cur_month then
insert(output, " " .. cur_year)
else
insert(output, " " .. cur_year)
end
end
elseif date or yearobj then
insert(output, format_date_or_year_month(date, yearobj, monthobj, day_explicitly_given, "date"))
elseif not maintenance_line_no_date then
-- Not main quote date. Return nil, caller will handle.
return nil, nil
elseif not getp("nodate") then
local accessdate = getp("accessdate")
if accessdate then
local explicit_day_given = date_has_day_specified(accessdate, "accessdate")
insert(output, format_bold_date(accessdate, explicit_day_given, "accessdate") .. " (last accessed)")
else
if mw.title.getCurrentTitle().namespace ~= 10 then
return maintenance_line(maintenance_line_no_date), true
end
return nil, nil
end
end
return ine(concat(output)), nil
end
local function tag_with_cite(txt)
return "<cite>" .. txt .. "</cite>"
end
-- Display the source line of the quote, above the actual quote text. This contains the majority of the logic of this
-- module (formerly contained in {{quote-meta/source}}).
function export.source(args, alias_map, format_as_cite, other_controls)
local tracking_categories = {}
local argslang = args[1] or args.lang
if not argslang then
-- For the moment, only trigger an error on mainspace pages and
-- other pages that are not user pages or pages containing discussions.
-- These are the same pages that appear in the appropriate tracking
-- categories. User and discussion pages have not generally been
-- fixed up to include a language code and so it's more helpful
-- to use a maintenance line than signal an error.
local current_title = mw.title.getCurrentTitle()
if not (current_title.namespace == 10 or page_should_be_ignored(current_title.fullText)) then
require(languages_error_module)(nil, 1)
end
end
-- Given a canonical param, convert it to the original parameter specified by the user (which may have been an
-- alias).
local function alias(param)
return alias_map[param] or param
end
local output, sep = {}
local overrides = other_controls and other_controls.overrides or {}
-- Add text to the output. The text goes into a list, and we concatenate all the list components together at the
-- end. To make it easier to handle comma-separated items, we keep track (in `sep`) of the separator (if any) that
-- needs to be inserted before the next item added. For example, if we're in the "newversion" code (ind ~= ""), and
-- there's no title and no URL, then the first time we add anything after the title, we don't want to add a
-- separating comma because the preceding text will say "republished " or "republished as " or "translated as " or
-- similar. In all- other cases, we do want to add a separating comma. The bare add() function reset the separator
-- to be nothing, while the add_with_sep() function resets the separator to be the value of `next_sep` (defaulting
-- to ", "), so the next time around we do add a comma to separate `text` from the preceding piece of text.
local function add(text)
if sep then
insert(output, sep)
end
insert(output, text)
sep = nil
end
local function add_with_sep(text, next_sep)
add(text)
sep = next_sep or ", "
end
-- FIXME: This is all very over-engineered, which makes it slow and memory-inefficient.
-- Return a function that generates the actual parameter name associated with a base param (e.g. "author", "last").
-- The actual parameter name may have an index added (an empty string for the first set of params, e.g. author=,
-- last=, or a numeric index for further sets of params, e.g. author2=, last2=, etc.).
local function make_get_full_paramname(ind)
return function(param)
return param .. ind
end
end
-- Function to fetch the actual parameter name associated with a base param (see make_get_full_paramname() above).
-- Assigned at various times below by calling make_get_full_paramname(). We do it this way so that we can have
-- wrapper functions that access params and define them only once.
local get_full_paramname
-- Return two values: the value of a parameter given the base param name (which may have a numeric index added),
-- and the parameter name from which the value was fetched (which may be an alias, i.e. you can't necessarily fetch
-- the parameter value from args[] given this name). The base parameter can be a list of such base params, which
-- are checked in turn, or nil, in which case nil is returned.
local function a_with_name(param)
if not param then
return nil
elseif type(param) ~= "table" then
local fullname = get_full_paramname(param)
return args[fullname], alias(fullname)
end
for _, par in ipairs(param) do
local val, fullname = a_with_name(par)
if val then
return val, alias(fullname)
end
end
return nil
end
-- Fetch the value of a parameter given the base param name (which may have a numeric index added). The base
-- parameter can be a list of such base params, which are checked in turn, or nil, in which case nil is returned.
local function a(param)
return (a_with_name(param))
end
-- Identical to a_with_name(param) except that it verifies that no space is present. Should be used for URL's.
local function aurl_with_name(param)
local value, fullname = a_with_name(param)
if value and value:find(" ") and not value:find("%[") then
error(("URL not allowed to contain a space, but saw |%s=%s"):format(fullname, value))
end
return value, fullname
end
-- Identical to a(param) except that it verifies that no space is present. Should be used for URL's.
local function aurl(param)
return (aurl_with_name(param))
end
-- Convenience function to fetch a parameter that may be in a foreign language or text (and may consequently have
-- a language prefix and/or inline modifiers), parse the annotations and convert the result into a formatted string.
-- This is the same as parse_and_format_annotated_text() below but also returns the full param name as the second
-- return value.
local function parse_and_format_annotated_text_with_name(param, tag_text_func, tag_gloss_func)
local val, fullname = a_with_name(param)
local obj = parse_annotated_text(val, fullname)
return format_annotated_text(obj, tag_text_func, tag_gloss_func), fullname
end
-- Convenience function to fetch a parameter that may be in a foreign language or text (and may consequently have
-- a language prefix and/or inline modifiers), parse the modifiers and convert the result into a formatted string.
-- This is a wrapper around parse_annotated_text() and format_annotated_text(). `param` is the base parameter name (see
-- a_with_name()), `tag_text_func` is an optional function to tag the parameter text after all other processing (e.g.
-- wrap in <cite>...</cite> tags), and `tag_gloss_func` is a similar function for the parameter translation/gloss.
local function parse_and_format_annotated_text(param, tag_text_func, tag_gloss_func)
return (parse_and_format_annotated_text_with_name(param, tag_text_func, tag_gloss_func))
end
-- Convenience function to fetch a multivalued parameter that may be in a foreign language or text (and may
-- consequently have a language prefix and/or inline modifiers), parse the modifiers and convert the result into a
-- formatted string. This is the multivalued analog to parse_and_format_annotated_text_with_name() and returns two
-- values, the formatted string and the full name of the parameter fetched. `delimiter` is as in
-- format_multivalued_annotated_text().
local function parse_and_format_multivalued_annotated_text_with_name(param, delimiter, tag_text_func, tag_gloss_func)
local val, fullname = a_with_name(param)
local objs = parse_multivalued_annotated_text(val, fullname)
local num_objs = objs and #objs or 0
return format_multivalued_annotated_text(objs, delimiter, tag_text_func, tag_gloss_func), fullname, num_objs
end
-- Convenience function to fetch a multivalued parameter that may be in a foreign language or text (and may
-- consequently have a language prefix and/or inline modifiers), parse the modifiers and convert the result into a
-- formatted string. This is the multivalued analog to parse_and_format_annotated_text(). `delimiter` is as in
-- format_multivalued_annotated_text().
local function parse_and_format_multivalued_annotated_text(param, delimiter, tag_text_func, tag_gloss_func)
return (parse_and_format_multivalued_annotated_text_with_name(param, delimiter, tag_text_func, tag_gloss_func))
end
-- This determines whether to display "Mary Bloggs, transl." (if there's no author preceding) or "translated by
-- Mary Bloggs" (if there's an author preceding).
local author_outputted = false
-- When formatting as a citation, the priority is to display a name and a date before the book/chapter title
-- this tracks whether or not the author/date has been displayed
local date_outputted, formatted_date, formatted_origdate = false
local function add_date(no_paren)
if not date_outputted then
if no_paren then
sep = ", "
else
sep = " "
end
if formatted_date then
if no_paren then
add(formatted_date)
else
add("(" .. formatted_date .. ")")
end
end
if formatted_origdate then
add(SPACE_LBRAC .. formatted_origdate .. RBRAC)
end
sep = ", "
date_outputted = true
end
end
local function is_anonymous(val)
return val:match("^[Aa]nonymous$") or val:match("^[Aa]non%.?$")
end
-- Add a formatted author (whose values may be specified using `author` or, for compatibility purposes, split
-- among various parameters):
-- * `author` is the value of the author param (e.g. "author", "author2" or "2ndauthor"), and `author_fullname` is
-- the full parameter name holding that value;
-- * `trans_author` is the optional value of the param holding the gloss/translation of the author, and
-- `trans_author_fullname` is the full parameter name holding that value (or nil for no such parameter);
-- * `authorlink` is the value of the authorlink param, which holds the Wikipedia link of the author(s) in `author`,
-- and `authorlink_fullname` is the full parameter name holding that value;
-- * `trans_authorlink` is the optional value of the param holding the Wikipedia link of the gloss/translation of
-- the author, and `trans_authorlink_fullname` is the full parameter name holding that value (or nil for no such
-- parameter);
-- * `first` is the value of the parameter holding the first name of the author, and `first_fullname` is the full
-- parameter name holding that value;
-- * `trans_first` is the value of the corresponding parameter holding the gloss/translation of the first name
-- (e.g. "trans-first"), and `trans_first_fullname` is the full parameter name holding that value (or nil for
-- no such parameter);
-- * `last` is the value of the parameter holding the last name of the author, and `last_fullname` is the full
-- parameter name holding that value;
-- * `trans_last` is the value of the corresponding parameter holding the gloss/translation of the last name
-- (e.g. "trans-last"), and `trans_last_fullname` is the full parameter name holding that value (or nil for
-- no such parameter).
-- * `last_first` if set, when parameters `first` and `last` are used, display the author name as "last, first"
local function add_author(
author,
author_fullname,
trans_author,
trans_author_fullname,
authorlink,
authorlink_fullname,
trans_authorlink,
trans_authorlink_fullname,
first,
first_fullname,
trans_first,
trans_first_fullname,
last,
last_fullname,
trans_last,
trans_last_fullname,
last_first
)
local function make_author_with_url(txt, txtparam, authorlink, authorlink_param)
if authorlink then
if authorlink:find("%[%[") then
error(("Can't specify links in |%s=%s"):format(authorlink_param, authorlink))
end
if txt:find("%[%[") then
error(("Can't specify links in %s=%s"):format(txtparam, txt))
end
return "[[w:" .. authorlink .. "|" .. txt .. "]]"
else
return txt
end
end
local num_authorobjs
if author then
local authorobjs =
parse_multivalued_annotated_text(author, author_fullname, trans_author, trans_author_fullname)
num_authorobjs = #authorobjs
if num_authorobjs == 1 then
if is_anonymous(authorobjs[1].text) then
authorobjs[1].text = "anonymous author"
authorobjs[1].link = "anonymous author"
end
if authorlink then
authorobjs[1].text = make_author_with_url(
authorobjs[1].text,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
authorobjs[1].link = make_author_with_url(
authorobjs[1].link,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
end
if authorobjs[1].gloss and trans_authorlink then
authorobjs[1].gloss = make_author_with_url(
authorobjs[1].gloss,
("<t:...> in |%s"):format(author_fullname),
trans_authorlink,
"|" .. trans_author_fullname
)
end
add(format_multivalued_annotated_text(authorobjs))
elseif trans_authorlink then
error(
(
"Can't specify |%s= along with multiple semicolon-separated entities in |%s=; use the "
.. "<t:...> inline modifier attached to the individual entities and put the link directly "
.. "in the value of the inline modifier"
):format(trans_authorlink_fullname, author_fullname)
)
else
-- Allow an authorlink with multiple authors, e.g. for use with |author=Max Mills; Harvey Mills
-- with |authorlink=Max and Harvey. For this we have to generate the entire text and link it
-- all.
local formatted_text = format_multivalued_annotated_text(authorobjs)
if authorlink then
formatted_text = make_author_with_url(
formatted_text,
"|" .. author_fullname,
authorlink,
"|" .. authorlink_fullname
)
end
add(formatted_text)
end
else
num_authorobjs = 1
-- Author separated into first name + last name. We don't currently support non-Latin-script
-- authors separated this way and probably never will.
if first then
if last_first then
author = last .. ", " .. first
else
author = first .. " " .. last
end
else
author = last
end
if authorlink then
local authorparam = first and ("|%s |%s"):format(first_fullname, last_fullname) or "|" .. last_fullname
author = make_author_with_url(author, authorparam, authorlink, authorlink_fullname)
end
local trans_author
if trans_last then
if trans_first then
trans_author = trans_first .. " " .. trans_last
else
trans_author = trans_last
end
if trans_authorlink then
local trans_authorparam = trans_first
and ("|%s |%s"):format(trans_first_fullname, trans_last_fullname)
or "|" .. trans_last_fullname
trans_author = make_author_with_url(
trans_author,
trans_authorparam,
trans_authorlink,
trans_authorlink_fullname
)
end
end
add(author)
if trans_author then
add(SPACE_LBRAC)
add(trans_author)
add(RBRAC)
end
end
author_outputted = true
return num_authorobjs
end
local function add_authorlike(
param,
prefix_with_preceding_authors,
suffix_without_preceding_authors,
suffix_if_multiple,
anonymous_suffix
)
local delimiter = author_outputted and "and" or ", "
local entities, _, num_entities = parse_and_format_multivalued_annotated_text_with_name(param, delimiter)
if not entities then
return
end
if is_anonymous(entities) then
-- If tlr=anonymous or similar given, display as "anonymous translator" or similar. If a specific
-- anonymous suffix not given, try to derive the anonymous suffix from the non-preceding-author suffix.
if not anonymous_suffix then
local cleaned_suffix = suffix_without_preceding_authors
:gsub(" ", " ")
:gsub(" ", " ")
:gsub(" ", " ")
:gsub("[", "[")
:gsub("]", "]")
cleaned_suffix = mw.text.trim(cleaned_suffix)
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^, (.*)$")
end
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^%((.*)%)$")
end
if not anonymous_suffix then
anonymous_suffix = " " .. cleaned_suffix:match("^%[(.*)%]$")
end
if not anonymous_suffix then
anonymous_suffix = suffix_without_preceding_authors
end
end
add_with_sep("anonymous" .. anonymous_suffix)
elseif prefix_with_preceding_authors and (author_outputted or not suffix_without_preceding_authors) then
add_with_sep(prefix_with_preceding_authors .. entities)
elseif suffix_if_multiple and num_entities > 1 then
add_with_sep(entities .. suffix_if_multiple)
else
add_with_sep(entities .. suffix_without_preceding_authors)
end
author_outputted = true
end
local function add_authorlabel()
local default_authorlabel = a("default-authorlabel")
if default_authorlabel and yesno(a("authorlabel"), true) then
sep = nil
add_with_sep(" " .. default_authorlabel)
end
end
local function has_new_title_or_author()
return args["2ndauthor"]
or args["2ndlast"]
or args.chapter2
or args.title2
or args.tlr2
or args.mainauthor2
or args.editor2
or args.editors2
or args.compiler2
or args.compilers2
or args.director2
or args.directors2
end
local function has_newversion()
return args.newversion or args.location2 or has_new_title_or_author()
end
-- Handle chapter=, section=, etc. `param` is the base name of the parameter in question, e.g. "chapter" or
-- "section". If numeric (either Arabic or Roman), add `numeric_prefix`; otherwise, parse as textual (allowing for
-- language prefixes, inline modifiers, etc.), prefix with `textual_prefix` (if given) and suffix with
-- `textual_suffix` (if given). Also checks for and handles the following (assuming param == "chapter"):
-- * chapterurl=: URL of the chapter.
-- * trans-chapter=: Chapter translation (can be given using an inline modifier <t:...>).
-- * chapter_number=: Chapter number, when chapter= is also given (otherwise put the chapter number in chapter=).
-- * chapter_plain=: Plain version of the chapter number; the "chapter " prefix isn't added.
-- * chapter_series=: Series that the chapter is within (used e.g. for journal articles part of a series).
-- * chapter_seriesvolume=: Volume of the series (compare seriesvolume=).
--
-- Returns nil if no value specified for the main parameter, otherwise the formatted value.
local function format_chapterlike(param, numeric_prefix, textual_prefix, textual_suffix)
local chap, chap_fullname = a_with_name(param)
local chap_num, chap_num_fullname = a_with_name(param .. "_number")
local chap_plain, chap_plain_fullname = parse_and_format_annotated_text_with_name(param .. "_plain")
if chap_num and chap_plain then
error(("Specify only one of |%s= or %s="):format(chap_num_fullname, chap_plain_fullname))
end
local chap_series, chap_series_fullname =
parse_and_format_annotated_text_with_name(param .. "_series", tag_with_cite, tag_with_cite)
local chap_seriesvolume, chap_seriesvolume_fullname =
parse_and_format_annotated_text_with_name(param .. "_seriesvolume")
if chap_series then
chap_series = ", " .. chap_series
end
if chap_seriesvolume then
if not chap_series then
error(("Cannot specify |%s= without %s="):format(chap_series_fullname, chap_seriesvolume_fullname))
end
chap_series = chap_series .. " (" .. chap_seriesvolume .. ")"
end
local chapterurl
local function make_chapter_with_url(chap)
if chapterurl then
return "[" .. chapterurl .. " " .. chap .. "]"
else
return chap
end
end
if not chap then
if chap_num then
error(
("Cannot specify |%s= without |%s=; put the numeric value in |%s= directly"):format(
chap_num_fullname,
chap_fullname,
chap_fullname
)
)
end
if chap_plain then
chapterurl = aurl(param .. "url")
return make_chapter_with_url(chap_plain .. (chap_series or ""))
end
return nil
end
local cleaned_chap = chap:gsub("<sup>[^<>]*</sup>", ""):gsub("[*+#]", "")
chapterurl = aurl(param .. "url")
local formatted
if numeric_prefix and get_number(cleaned_chap) then
-- Arabic chapter number
formatted = numeric_prefix .. make_chapter_with_url(chap)
elseif
numeric_prefix
and cleaned_chap:match("^[mdclxviMDCLXVI]+$")
and roman_to_arabic(cleaned_chap, true)
and (not overrides[param] or not overrides[param].noroman)
then
-- Roman chapter number
formatted = numeric_prefix .. make_chapter_with_url(upper(chap))
else
-- strip leading ! (used to force text-mode for titles that look like Roman numerals like "mil" and "dill")
if chap:find("^!") then
chap = chap:gsub("^!", "")
end
-- Must be a chapter name
local chapterobj = parse_annotated_text(chap, chap_fullname, a("trans-" .. param))
chapterobj.text = make_chapter_with_url(chapterobj.text)
chapterobj.link = make_chapter_with_url(chapterobj.link)
formatted = (textual_prefix or "") .. format_annotated_text(chapterobj) .. (textual_suffix or "")
end
if chap_num or chap_plain then
-- NOTE: Up above we throw an error if both chap_num and chap_plain are specified.
formatted = formatted .. " (" .. (chap_plain or numeric_prefix .. chap_num) .. ")"
end
if chap_series then
formatted = formatted .. chap_series
end
return formatted
end
-- This handles everything after displaying the author, starting with the chapter and ending with page, column,
-- line and then other=. It is currently called twice: Once to handle the main portion of the citation, and once to
-- handle a "newversion" citation. `ind` is either "" for the main portion or a number (currently only 2) for a
-- "newversion" citation. In a few places we conditionalize on `ind` to take actions depending on its value.
local function postauthor(ind, num_authors, format_as_cite)
get_full_paramname = make_get_full_paramname(ind)
if author_outputted then
add_authorlabel()
end
local coauthors = parse_and_format_multivalued_annotated_text("coauthors", "and")
if coauthors then
local with_prefix = ""
if author_outputted then
with_prefix = "dengan "
if num_authors == 1 then
sep = " "
end
end
add_with_sep(with_prefix .. coauthors)
author_outputted = true
end
add_authorlike("quotee", "memetik ", ", pemetik", ", pemetik")
if format_as_cite and author_outputted and not date_outputted then
add_date()
sep = ", "
end
add_authorlike("chapter_tlr", "diterjemah oleh ", ", penterjemah", nil, " penterjemah")
local function add_sg_and_pl_authorlike(noun, verbed)
local sgparam = noun
local plparam = noun
local sgval, sgval_fullname = a_with_name(sgparam)
local plval, plval_fullname = a_with_name(plparam)
if sgval and plval then
error(("Can't specify both |%s= and |%s="):format(sgval_fullname, plval_fullname))
end
if sgval or plval then
local verbed_by = verbed .. " oleh "
local comma_sgnoun = ", " .. noun
local comma_plnoun = ", " .. noun
add_authorlike(sgparam, verbed_by, comma_sgnoun, comma_plnoun)
add_authorlike(plparam, verbed_by, comma_plnoun)
end
end
local formatted_entry = format_chapterlike("entry", nil, "“", "”")
local formatted_chapter = format_chapterlike("chapter", "chapter ", "“", "”")
local function add_entry()
if formatted_entry then
add_with_sep(formatted_entry)
if not a("notitle") then
add("dalam ")
author_outputted = false
else
author_outputted = true
end
formatted_entry = nil
end
end
local function add_chapter()
add_entry()
if formatted_chapter then
add_with_sep(formatted_chapter)
if not a("notitle") then
add("dalam ")
author_outputted = false
end
formatted_chapter = nil
end
end
local function add_actor_role(format_as_cite)
local role = parse_and_format_multivalued_annotated_text("role", "and")
local actor_val, actor_fullname = a_with_name("actor")
local actor_objs = parse_multivalued_annotated_text(actor_val, actor_fullname)
local actor = format_multivalued_annotated_text(actor_objs, "and")
if format_as_cite then
if role then
if actor then
add_with_sep(actor .. " sebagai ")
end
sep = nil
add_with_sep(role)
elseif actor then
add_with_sep(actor .. " (" .. (#actor_objs > 1 and "actors" or "actor") .. ")")
end
else
if role then
add_with_sep("diucapkan oleh " .. role)
if actor then
sep = nil
add_with_sep(" (" .. actor .. ")")
end
elseif actor then
add_with_sep(actor .. " (" .. (#actor_objs > 1 and "actors" or "actor") .. ")")
end
end
end
if format_as_cite then
if date_outputted then
add_chapter()
end
local output_len = #output
local mainauthor = parse_and_format_multivalued_annotated_text("mainauthor")
if mainauthor then
add_with_sep(mainauthor)
end
-- quote-* templates display "jobbed by name" after the author, controlled by the author_outputted flag
author_outputted = false
add_authorlike("tlr", "diterjemah oleh ", ", penterjemah", nil, " penterjemah")
author_outputted = false
add_sg_and_pl_authorlike("editor", "edited")
add_sg_and_pl_authorlike("compiler", "compiled")
add_sg_and_pl_authorlike("director", "directed")
add_authorlike("lyricist", nil, " (lirik)", nil, " penulis lirik")
add_authorlike("lyrics-translator", nil, " (terjemahan)", nil, " penterjemah lirik")
add_authorlike("composer", nil, " (muzik)", nil, " penggubal")
add_actor_role("format_as_cite")
-- if the output length has changed, a credit name has been printed
-- and we can print the date
if output_len ~= #output then
author_outputted = true
add_date()
end
add_chapter()
else
add_chapter()
local mainauthor = parse_and_format_multivalued_annotated_text("mainauthor")
if mainauthor then
add_with_sep(mainauthor)
author_outputted = true
end
add_authorlike("tlr", "diterjemah oleh ", ", penterjemah", nil, " penterjemah")
add_sg_and_pl_authorlike("editor", "edited")
add_sg_and_pl_authorlike("compiler", "compiled")
add_sg_and_pl_authorlike("director", "directed")
add_authorlike("lyricist", nil, " (lirik)", nil, " penulis lirik")
add_authorlike("lyrics-translator", nil, " (terjemahan)", nil, " penterjemah lirik")
add_authorlike("composer", nil, " (muzik)", nil, " penggubal")
end
local title, title_fullname = a_with_name("title")
local need_comma = false
if title then
local titleobj = parse_annotated_text(title, title_fullname, a("trans-title"))
add(format_annotated_text(titleobj, tag_with_cite, tag_with_cite))
local series = parse_and_format_annotated_text("series")
if series then
add(" (" .. series)
local seriesvolume = parse_and_format_annotated_text("seriesvolume")
if seriesvolume then
add(SEMICOLON_SPACE .. seriesvolume)
end
add(")")
end
need_comma = true
elseif ind == "" then
if not a("notitle") then
add(maintenance_line("Please provide the book title or journal name"))
need_comma = true
end
end
local archiveurl, archiveurl_fullname = aurl_with_name("archiveurl")
local url, url_fullname = aurl_with_name("url")
local urls, urls_fullname = aurl_with_name("urls")
if url and urls then
error(("Supply only one of |%s= and |%s="):format(url_fullname, urls_fullname))
end
local function verify_title_supplied(url_name)
-- There are too many cases of this to throw an error at this time.
-- if not title then
-- error(("If |%s= is given, |%s= must also be supplied"):format(url_name, title_fullname))
-- end
end
if archiveurl or url then
verify_title_supplied(archiveurl and archiveurl_fullname or url_fullname)
sep = nil
add("‎<sup>[" .. (archiveurl or url) .. "]</sup>")
elseif urls then
verify_title_supplied(urls_fullname)
sep = nil
add("‎<sup>" .. urls .. "</sup>")
end
-- display (in Language) if language is provided and is not English and not overriden by termlang or worklang
if format_as_cite and ind == "" and not (args.termlang or args.worklang) and (args[1] or args.lang) then
local lang = get_first_lang(args[1] or args.lang)
if lang then
local langcode = lang:getCode()
if not (langcode == "und" or langcode == "ms") then
local langs = format_langs(args[1] or args.lang)
if langs then
add(" (dalam bahasa " .. langs .. ")")
end
end
end
end
if need_comma then
sep = ", "
end
local edition, edition_fullname = parse_and_format_annotated_text_with_name("edition")
local edition_plain, edition_plain_fullname = parse_and_format_annotated_text_with_name("edition_plain")
if edition and edition_plain then
error(("Supply only one of |%s= and |%s="):format(edition_fullname, edition_plain_fullname))
end
if edition then
add_with_sep("edisi " .. edition)
end
if edition_plain then
add_with_sep(edition_plain)
end
-- Display a numeric param such as page=, volume=, column=. For each `paramname`, four params are actually
-- recognized, e.g. for paramname == "page", the params page=, pages=, page_plain= and pageurl= are recognized
-- and checked (or the same with an index, e.g. page2=, pages2=, page_plain2= and pageurl2= respectively if
-- ind == "2"). Only one of the first three can be specified; an error results if more than one are given.
-- If none are given, the return value is nil; otherwise it is a string. The numeric spec is taken directly
-- from e.g. page_plain= if given; otherwise if e.g. pages= is given, or if page= is given and looks like a
-- combination of numbers (i.e. it has a hyphen or dash in it, a comma, or the word " and "), it is prefixed
-- by `singular_desc` + "s" (e.g. "pages "), otherwise it is prefixed by just `singular_desc` (e.g. "page ").
-- (As a special case, if either e.g. page=unnumbered or pages=unnumbered is given, the numeric spec is
-- "unnumbered page".) The resulting spec is returned directly unless e.g. pageurl= is given, in which case
-- it is linked to the specified URL. Note that any of the specs can be foreign text, e.g. foreign numbers
-- (including with optional inline modifiers), and such text is handled appropriately.
local function format_numeric_param(paramname, singular_desc)
local sgval = a_with_name(paramname)
local sgobj = parse_annotated_text(sgval, paramname)
local plparamname = paramname
local plval = a_with_name(plparamname)
local plobj = parse_annotated_text(plval, plparamname)
local plainval, plain_fullname = parse_and_format_annotated_text_with_name(paramname .. "_plain")
local numspec
if not sgval and not plval and not plainval then
return
elseif plainval and (sgval or plval) then
error(("Can't specify " .. plain_fullname .. " with " .. paramname .. " or " .. plparamname))
elseif sgval and plval then
-- if both singular and plural, display "page 1 of 1-10"
numspec = singular_desc .. " " .. sgval .. " daripada " .. plval
else
-- Merge page= and pages= and treat alike because people often mix them up in both directions.
if plainval then
numspec = plainval
else
local val = sgobj and sgobj.text or plobj.text
if val == "unnumbered" then
numspec = "unnumbered " .. singular_desc
else
local desc
if val:find("^!") then
val = val:gsub("^!", "")
desc = sgval and singular_desc or pluralize(singular_desc)
else
local check_val = val
if check_val:find("%[") then
check_val = remove_links(check_val)
-- convert URL's of the form [URL DISPLAY] to the displayed value
check_val = check_val:gsub("%[[^ %[%]]* ([^%[%]]*)%]", "%1")
end
-- in case of negative page numbers (do they exist?), don't treat as multiple pages
check_val = check_val:gsub("^%-", "")
-- replace HTML entity en-dashes and em-dashes with their literal codes
check_val = check_val:gsub("–", "–")
check_val = check_val:gsub("–", "–")
check_val = check_val:gsub("—", "—")
check_val = check_val:gsub("—", "—")
-- Check for en-dash or em-dash, or two numbers (possibly with stuff after like 12a-15b)
-- separated by a hyphen or by comma a followed by a space (to avoid firing on thousands separators).
if
umatch(check_val, "[–—]")
or check_val:find(" and ")
or check_val:match("%d+[^ ]* *%- *%d+")
or check_val:match("%d+[^ ]* *, +%d+")
then
desc = pluralize(singular_desc)
else
desc = singular_desc
end
end
local obj = sgobj or plobj
obj.text = val
if obj.link:find("^!") then
obj.link = obj.link:gsub("^!", "")
end
val = format_annotated_text(obj)
numspec = desc .. " " .. val
end
end
end
local url = a(paramname .. "url")
if url then
return "[" .. url .. " " .. numspec .. "]"
else
return numspec
end
end
local volume = format_numeric_param("volume", a("volume_prefix") or "volume")
if volume then
add_with_sep(volume)
end
local issue = format_numeric_param("issue", a("issue_prefix") or "number")
if issue then
add_with_sep(issue)
end
-- number= is an alias for issue= (except in {{quote-av}}, where it is the episode number)
local number = format_numeric_param("number", a("number_prefix") or "number")
if number then
add_with_sep(number)
end
local annotations = {}
local genre = a("genre")
if genre then
insert(annotations, genre)
end
local format = a("format")
if format then
insert(annotations, format)
end
local medium = a("medium")
if medium then
insert(annotations, medium)
end
-- Now handle the display of language annotations like "(in French)" or
-- "(quotation in Nauruan; overall work in German)".
local quotelang = args[1] or args.lang
if not quotelang then
if ind == "" then
-- This can only happen for certain non-mainspace pages, e.g. Talk pages; otherwise an error is thrown
-- above.
insert(annotations, maintenance_line("Please specify the language of the quote using |1="))
else
-- do nothing in newversion= portion
end
elseif ind == "" then
local worklang = a("worklang")
local termlang = a("termlang")
worklang = worklang or quotelang
termlang = termlang or quotelang
if worklang == quotelang then
if worklang == termlang then
-- do nothing
else
insert(annotations, "dalam " .. format_langs(quotelang))
end
else
if quotelang ~= termlang then
insert(annotations, "petikan dalam bahasa " ..format_langs(quotelang))
end
insert(annotations, "karya secara keseluruhannya dalam bahasa " .. format_langs(worklang))
end
else
local lang2 = a("lang2")
if lang2 then
insert(annotations, "dalam " .. format_langs(lang2))
end
end
if #annotations > 0 then
sep = nil
add_with_sep(" (" .. concat(annotations, SEMICOLON_SPACE) .. ")")
end
local artist = parse_and_format_multivalued_annotated_text("artist", "and")
if artist then
add_with_sep("performed by " .. artist)
end
local feat = parse_and_format_multivalued_annotated_text("feat", "and")
if feat then
sep = " "
add_with_sep("ft. " .. feat)
end
if not format_as_cite then
add_actor_role()
end
local others = parse_and_format_annotated_text("others")
if others then
add_with_sep(others)
end
local quoted_in = parse_and_format_annotated_text("quoted_in", tag_with_cite, tag_with_cite)
if quoted_in then
add_with_sep("dipetik dalam " .. quoted_in)
insert(tracking_categories, "Quotations using quoted-in parameter")
end
local location = parse_and_format_multivalued_annotated_text("location", "; ")
local publisher = parse_and_format_multivalued_annotated_text("publisher", "; ")
if publisher then
if location then
add_with_sep(location) -- colon
sep = ": " -- colon
end
add_with_sep(publisher)
elseif location then
add_with_sep(location)
end
if not date_outputted then
add_date("no_paren")
end
local source = parse_and_format_multivalued_annotated_text("source", "and")
if source then
add_with_sep("sourced from " .. source)
end
local original = parse_and_format_annotated_text("original", tag_with_cite, tag_with_cite)
local by = parse_and_format_multivalued_annotated_text("by", "and")
local origtype = a("deriv") or "translation"
if original or by then
add_with_sep(origtype .. " of " .. (original or "original") .. (by and " by " .. by or ""))
end
-- Handle origlang=, origworklang=. How we handle them depends on whether the original title or author are explicitly
-- given.
local origlang = a("origlang")
local origworklang = a("origworklang")
local origlangtext, origworklangtext
if origlang then
origlangtext = "dalam " .. format_langs(origlang)
end
if origworklang then
origworklangtext = "overall work in " .. format_langs(origworklang)
end
if origlang or origworklang then
if original or by then
local orig_annotations = {}
if origlangtext then
insert(orig_annotations, origlangtext)
end
if origworklangtext then
insert(orig_annotations, origworklangtext)
end
sep = nil
add_with_sep(" (" .. concat(orig_annotations, SEMICOLON_SPACE) .. ")")
else
add_with_sep(origtype .. " of original" .. (origlangtext and " " .. origlangtext or ""))
if origworklangtext then
sep = nil
add_with_sep(" (" .. origworklangtext .. ")")
end
end
end
if ind ~= "" and has_newversion() then
local formatted_new_date = format_date_args(a, get_full_paramname, alias_map, "", "", nil, "Please provide a date or year", true)
if formatted_new_date then
add_with_sep(formatted_new_date)
end
end
-- Fetch date_published=/year_published=/month_published= and format appropriately.
local formatted_date_published = format_date_args(a, get_full_paramname, alias_map, "", "_published", nil, nil, true)
local platform = parse_and_format_multivalued_annotated_text("platform", "and")
if formatted_date_published then
add_with_sep("published " .. formatted_date_published .. (platform and " via " .. platform or ""))
elseif platform then
add_with_sep("via " .. platform)
end
-- From here on out, there should always be a preceding item, so we
-- can dispense with add_with_sep() and always insert the comma.
sep = nil
local function small(txt)
add(", <small>")
add(txt)
add("</small>")
end
-- Add an identifier to a book or article database such as DOI, ISBN, JSTOR, etc. `param_or_params`
-- is a string identifying the base param, or a list of such strings to check in turn. If found, the value
-- of the parameter is processed using `process` (a function of one argument, defaulting to mw.uri.encode()),
-- and then the actual URL to insert is generated by preceding with `pretext`, following with `posttext`,
-- and running the resulting string through small(), which first adds a comma and then the URL in small font.
local function add_identifier(param_or_params, pretext, posttext, process)
local val = a(param_or_params)
if val then
val = (process or mw.uri.encode)(val)
small(pretext .. val .. posttext)
end
end
add_identifier("bibcode", "[https://adsabs.harvard.edu/abs/", " →Bibcode]")
add_identifier("doi", '<span class="neverexpand">[https://doi.org/', " →DOI]</span>")
add_identifier("isbn", "", "", isbn)
add_identifier("issn", "", "", issn)
add_identifier("jstor", "[https://www.jstor.org/stable/", " →JSTOR]")
add_identifier("lccn", "", "", lccn)
add_identifier("oclc", "[https://search.worldcat.org/title/", " →OCLC]")
add_identifier("ol", "[https://openlibrary.org/works/OL", "/ →OL]")
add_identifier("pmid", "[https://www.ncbi.nlm.nih.gov/pubmed/", " →PMID]")
add_identifier("pmcid", "[https://www.ncbi.nlm.nih.gov/pmc/articles/", "/ →PMCID]")
add_identifier("ssrn", "[https://ssrn.com/abstract=", " →SSRN]")
-- add_identifier("urn", "", "", urn)
local id = a("id")
if id then
small(id)
end
archiveurl, archiveurl_fullname = aurl_with_name("archiveurl")
if archiveurl then
add(", diarkibkan daripada ")
local url, url_fullname = aurl_with_name("url")
if not url then
-- attempt to infer original URL from archive URL; this works at
-- least for Wayback Machine (web.archive.org) URL's
url = archiveurl:match("/(https?:.*)$")
if not url then
error(
("When |%s= is specified, |%s= must also be included"):format(archiveurl_fullname, url_fullname)
)
end
end
add("[" .. url .. " the original] on ")
local archivedate, archivedate_fullname = a_with_name("archivedate")
if archivedate then
add(format_date(archivedate))
elseif string.sub(archiveurl, 1, 28) == "https://web.archive.org/web/" then
-- If the archive is from the Wayback Machine, then it already contains the date
-- Get the date and format it
local wayback_date = string.sub(archiveurl, 29, 29 + 7)
wayback_date = string.sub(wayback_date, 1, 4)
.. "-"
.. string.sub(wayback_date, 5, 6)
.. "-"
.. string.sub(wayback_date, 7, 8)
add(format_date(wayback_date))
else
error(
("When |%s= is specified, |%s= must also be included"):format(
archiveurl_fullname,
archivedate_fullname
)
)
end
end
if a("accessdate") then
--Otherwise do not display here, as already used as a fallback for missing date= or year= earlier.
if (a("date") or a("nodate") or a("year")) and not a("archivedate") then
add(", retrieved " .. format_date(a("accessdate")))
end
end
local formatted_section = format_chapterlike("section", "section ")
if formatted_section then
add(", ")
add(formatted_section)
end
-- video game stuff
local system = parse_and_format_annotated_text("system")
if system then
add(", " .. system)
end
local scene = parse_and_format_annotated_text("scene")
if scene then
add(", scene: " .. scene)
end
local level = parse_and_format_annotated_text("level")
if level then
add(", level/area: " .. level)
end
local note = parse_and_format_annotated_text("note")
if note then
add(", " .. note)
end
local note_plain = parse_and_format_annotated_text("note_plain")
if note_plain then
add(" " .. note_plain)
end
-- Wrapper around format_numeric_param that inserts the formatted text with optional preceding text.
local function handle_numeric_param(paramname, singular_desc, pretext)
local numspec = format_numeric_param(paramname, singular_desc)
if numspec then
add((pretext or "") .. numspec)
end
end
handle_numeric_param("page", a("page_prefix") or "page", ", ")
handle_numeric_param("column", a("column_prefix") or "column", ", ")
handle_numeric_param("line", a("line_prefix") or "line", ", ")
-- FIXME: Does this make sense? What is other=?
local other = parse_and_format_annotated_text("other")
if other then
add(", " .. other)
end
end
local function add_authors(args, last_first)
-- Find maximum indexed author or last name.
local maxind = math.max(args.author.maxindex, args.last.maxindex)
-- Include max index of ancillary params so we get an error message about their use without the primary params.
local ancillary_params =
{"trans-author", "authorlink", "trans-authorlink", "first", "trans-first", "trans-last"}
for _, ancillary in ipairs(ancillary_params) do
maxind = math.max(maxind, args[ancillary].maxindex)
end
local num_authors = 0
for i = 1, maxind do
local ind = i == 1 and "" or i
local author, last = args.author[i], args.last[i]
if author or last then
local this_num_authors = add_author(
author,
"author" .. ind,
args["trans-author"][i],
"trans-author" .. ind,
args.authorlink[i],
"authorlink" .. ind,
args["trans-authorlink"][i],
"trans-authorlink" .. ind,
args.first[i],
"first" .. ind,
args["trans-first"][i],
"trans-first" .. ind,
last,
"last" .. ind,
args["trans-last"][i],
"trans-last" .. ind,
last_first
)
num_authors = num_authors + this_num_authors
sep = last_first and "; " or ", "
else
for _, cant_have in ipairs(ancillary_params) do
if args[cant_have][i] then
error(("Can't have |%s%s= without |author%s= or |last%s="):format(cant_have, ind, ind, ind))
end
end
end
end
return num_authors
end
local function add_newversion()
-- If there's a "newversion" section, add the new-version text.
if has_newversion() then
sep = nil
--Test for new version of work.
add(SEMICOLON_SPACE)
if args.newversion then -- newversion= is intended for English text, e.g. "quoted in" or "republished as".
add(args.newversion)
elseif not args.edition2 then
if has_new_title_or_author() then
add("republished as")
else
add("republished")
end
end
add(" ")
return ""
else
return ", "
end
end
------------------- Now we start outputting text ----------------------
local need_comma = false
-- Set this now so a() works just below.
get_full_paramname = make_get_full_paramname("")
if args.brackets then
add("[")
end
bold_year = not format_as_cite
year_last = format_as_cite
formatted_date, need_date = format_date_args(
a,
get_full_paramname,
alias_map,
nil,
nil,
bold_year,
"Can we [[:Category:Requests for date|date]] this quote?",
year_last
)
-- Fetch origdate=/origyear=/origmonth= and format appropriately.
formatted_origdate = format_date_args(a, get_full_paramname, alias_map, "orig", nil, nil, nil, year_last)
local num_authors, need_date
if format_as_cite then
num_authors = add_authors(args, "last_first")
if author_outputted then
sep = " "
end
-- Display all the text that comes after the author, for the main portion.
postauthor("", num_authors, "format_as_cite")
author_outputted = false
sep = add_newversion()
-- Add the newversion author(s).
if args["2ndauthor"] or args["2ndlast"] then
num_authors = add_author(
args["2ndauthor"],
"2ndauthor",
nil,
nil,
args["2ndauthorlink"],
"2ndauthorlink",
nil,
nil,
args["2ndfirst"],
"2ndfirst",
nil,
nil,
args["2ndlast"],
"2ndlast",
nil,
nil,
"last_first"
)
sep = ", "
else
for _, cant_have in ipairs{"2ndauthorlink", "2ndfirst"} do
if args[cant_have] then
error(("Can't have |%s= without |2ndauthor= or |2ndlast="):format(cant_have))
end
end
end
-- Display all the text that comes after the author, for the "newversion" section.
postauthor(2, num_authors, "format_as_cite")
else
if formatted_date then
need_comma = true
add(formatted_date)
end
if formatted_origdate then
need_comma = true
add(SPACE_LBRAC .. formatted_origdate .. RBRAC)
end
if need_comma then
sep = ", "
end
date_outputted = true
num_authors = add_authors(args)
-- Display all the text that comes after the author, for the main portion.
postauthor("", num_authors)
author_outputted = false
sep = add_newversion()
-- Add the newversion author(s).
if args["2ndauthor"] or args["2ndlast"] then
num_authors = add_author(
args["2ndauthor"],
"2ndauthor",
nil,
nil,
args["2ndauthorlink"],
"2ndauthorlink",
nil,
nil,
args["2ndfirst"],
"2ndfirst",
nil,
nil,
args["2ndlast"],
"2ndlast",
nil,
nil
)
sep = ", "
else
for _, cant_have in ipairs{"2ndauthorlink", "2ndfirst"} do
if args[cant_have] then
error(("Can't have |%s= without |2ndauthor= or |2ndlast="):format(cant_have))
end
end
end
-- Display all the text that comes after the author, for the "newversion" section.
postauthor(2, num_authors)
end
if not args.nocolon then
sep = nil
add(":")
elseif args.usenodot and not args.nodot then
add(".")
end
-- Concatenate output portions to form output text.
local output_text = concat(output)
-- Remainder of code handles adding categories. We add one or more of the following categories:
--
-- 1. [[Category:LANG terms with quotations]], based on the first language code in termlang= or 1=. Added to
-- mainspace, Reconstruction: and Appendix: pages as well as Citations: pages if the corresponding mainspace
-- page exists. Not added if nocat= is given. Note that [[Module:usex]] adds the same category using the same
-- logic, but we do it here too because we may not have a quotation to format. (We add in those circumstances
-- because typically when there's no quotation to format, it's because it's formatted manually underneath the
-- citation, or using {{ja-x}}, {{th-x}} or similar.)
-- 2. [[Category:Requests for date in LANG entries]], based on the first language code in 1=. Added to mainspace,
-- Reconstruction:, Appendix: and Citations: pages unless nocat= is given.
-- 3. [[Category:Quotations using nocat parameter]], if nocat= is given. Added to mainspace, Reconstruction:,
-- Appendix: and Citations: pages.
local categories = {}
local termlang = get_first_lang(args.termlang or argslang)
if args.nocat then
if format_as_cite then
insert(tracking_categories, "Citations using nocat parameter")
else
insert(tracking_categories, "Quotations using nocat parameter")
end
else
-- don't create language tracking categories for citations
if not format_as_cite then
local title
if args.pagename then -- for testing, doc pages, etc.
title = mw.title.new(args.pagename)
if not title then
error(("Bad value for `args.pagename`: '%s'"):format(args.pagename))
end
else
title = mw.title.getCurrentTitle()
end
-- Only add [[Citations:foo]] to [[:Category:LANG terms with quotations]] if [[foo]] exists.
local ok_to_add_cat
if title.nsText ~= "Citations" then
ok_to_add_cat = true
else
local mainspace_title = mw.title.new(title.text)
if mainspace_title and mainspace_title.exists then
ok_to_add_cat = true
end
end
if ok_to_add_cat then
insert(categories, termlang:getFullName() .. " terms with quotations")
end
end
if need_date then
local argslangobj = get_first_lang(argslang)
insert(categories, "Requests for date in " .. argslangobj:getCanonicalName() .. " entries")
end
end
return output_text .. (
not lang and "" or
(#categories > 0 and format_categories(categories, lang, args.sort) or "") .. (
#tracking_categories > 0
and format_categories(
tracking_categories,
lang,
args.sort,
nil,
not page_should_be_ignored(mw.title.getCurrentTitle().fullText)
)
or ""
)
)
end
-- Alias specs for type= and type2=. Each spec is `{canon, aliases, with_newversion}` where `canon` is the canonical
-- parameter (with "2" added if type2= is being handled), `aliases` is a comma-separated string of aliases (with "2"
-- added if type2= is being handled, except for numeric params), and `with_newversion` indicates whether we should
-- process this spec if type2= is being handled.
local type_alias_specs = {
av = {
{"author", "writer,writers", true},
{"chapter", "episode", true},
{"chapterurl", "episodeurl", true},
{"trans-chapter", "trans-episode", true},
{"chapter_tlr", "episode_tlr,episode_tlrs,episode_translator,episode_translators", true},
{"chapter_series", "episode_series", true},
{"chapter_seriesvolume", "episode_seriesvolume", true},
{"chapter_number", "episode_number", true},
{"chapter_plain", "episode_plain", true},
{"volume", "season", true},
{"volumes", "seasons", true},
{"volume_plain", "season_plain", true},
{"volumeurl", "seasonurl", true},
{"platform", "network", true},
},
book = {
{"author", "3"},
{"title", "4"},
{"url", "5"},
{"year", "2"},
{"page", "6"},
{"text", "7"},
{"t", "8"},
},
journal = {
{"year", "2"},
{"author", "3"},
{"chapter", "title,article,4", true},
{"chapterurl", "titleurl,articleurl", true},
{"trans-chapter", "trans-title,trans-article", true},
{"chapter_tlr", "title_tlr,title_tlrs,title_translator,title_translators,article_tlr,article_tlrs,article_translator,article_translators", true},
{"chapter_series", "title_series,article_series", true},
{"chapter_seriesvolume", "title_seriesvolume,article_seriesvolume", true},
{"chapter_number", "title_number,article_number", true},
{"chapter_plain", "title_plain,article_plain", true},
{"title", "journal,magazine,newspaper,work,5", true},
{"trans-title", "trans-journal,trans-magazine,trans-newspaper,trans-work", true},
{"tlr", "journal_tlr,journal_tlrs,journal_translator,journal_translators,magazine_tlr,magazine_tlrs,magazine_translator,magazine_translators,newspaper_tlr,newspaper_tlrs,newspaper_translator,newspaper_translators,work_tlr,work_tlrs,work_translator,work_translators", true},
{"url", "6,journalurl,magazineurl,newspaperurl,workurl", true},
{"page", "7"},
{"source", "newsagency,news_agency", true},
{"text", "8"},
{"t", "9"},
},
}
-- Process interally-handled aliases related to type= or type2=. `args` is a table of arguments; `typ` is the value of
-- type= or type2=; newversion=true if we're dealing with type2=; alias_map is used to keep track of alias mappings
-- seen.
local function process_type_aliases(args, typ, newversion, alias_map)
local ind = newversion and "2" or ""
local deprecated = ine(args.lang)
if not type_alias_specs[typ] then
local possible_values = {}
for possible, _ in pairs(type_alias_specs) do
insert(possible_values, possible)
end
sort(possible_values)
error(
("Unrecognized value '%s' for type%s=; possible values are %s"):format(
typ,
ind,
concat(possible_values, ",")
)
)
end
for _, alias_spec in ipairs(type_alias_specs[typ]) do
local canon, aliases, with_newversion = unpack(alias_spec)
if with_newversion or not newversion then
canon = canon .. ind
aliases = split(aliases, ",", true)
local saw_alias = nil
for _, alias in ipairs(aliases) do
if alias:match("^%d+$") then
alias = tonumber(alias)
if deprecated then
alias = alias - 1
end
else
alias = alias .. ind
end
if args[alias] then
if saw_alias == nil then
saw_alias = alias
else
error(("|%s= and |%s= are aliases; cannot specify a value for both"):format(saw_alias, alias))
end
end
end
if saw_alias and (not newversion or type(saw_alias) == "string") then
if args[canon] then
error(("|%s= is an alias of |%s=; cannot specify a value for both"):format(saw_alias, canon))
end
args[canon] = args[saw_alias]
-- Wipe out the original after copying. This is important in case of a param that has general significance
-- but has been redefined (e.g. {{quote-av}} redefines number= for the episode number, and
-- {{quote-journal}} redefines title= for the chapter= (article). It's also important due to unhandled
-- parameter checking.
args[saw_alias] = nil
alias_map[canon] = saw_alias
end
end
end
end
-- Clone and combine frame's and parent's args while also assigning nil to empty strings. Handle aliases and ignores.
local function clone_args(direct_args, parent_args)
local args = {}
-- Processing parent args must come first so that direct args override parent args. Note that if a direct arg is
-- specified but is blank, it will still override the parent arg (with nil).
for pname, param in pairs(parent_args) do
-- [[Special:WhatLinksHere/Wiktionary:Tracking/quote/param/PARAM]]
track("param/" .. pname)
args[pname] = ine(param)
end
-- Process ignores. The value of `ignore` is a comma-separated list of parameter names to ignore (erase). We need to
-- do this before aliases due to {{quote-song}}, which sets chapter= to the value of title= in the direct params and
-- sets title= to the value of album= using an alias. If we do the ignores after aliases, we get an error during alias
-- processing, saying that title= and its alias album= are both present.
local ignores = ine(direct_args.ignore)
if ignores then
for ignore in gsplit(ignores, "%s*,%s*") do
args[ignore] = nil
end
end
local alias_map = {}
local other_controls = {}
-- noroman
local noroman = ine(direct_args.noroman)
if noroman then
other_controls.overrides = other_controls.overrides or {}
for param in gsplit(noroman, "%s*,%s*") do
other_controls.overrides[param] = (other_controls.overrides[param] or {})
other_controls.overrides[param].noroman = true
end
end
-- Process internally-specified aliases using type= or type2=.
local typ = args.type or direct_args.type
if typ then
process_type_aliases(args, typ, false, alias_map)
end
local typ2 = args.type2 or direct_args.type2
if typ2 then
process_type_aliases(args, typ2, true, alias_map)
end
-- Process externally-specified aliases. The value of `alias` is a list of semicolon-separated specs, each of which
-- is of the form DEST:SOURCE,SOURCE,... where DEST is the canonical name of a parameter and SOURCE refers to an
-- alias. Whitespace is allowed between all delimiters. The order of aliases may be important. For example, for
-- {{quote-journal}}, title= contains the article name and is an alias of underlying chapter=, while journal= or
-- work= contains the journal name and is an alias of underlying title=. As a result, the title -> chapter alias
-- must be specified before the journal/work -> title alias.
--
-- Whenever we copy a value from argument SOURCE to argument DEST, we record an entry for the pair in alias_map, so
-- that when we would display an error message about DEST, we display SOURCE instead.
--
-- Do alias processing (and ignore and error_if processing) before processing direct_args so that e.g. we can set up
-- an alias of title -> chapter and then set title= to something else in the direct args ({{quote-hansard}} does
-- this).
--
-- FIXME: Delete this once we've converted all alias processing to internal.
local aliases = ine(direct_args.alias)
if aliases then
-- Allow and discard a trailing semicolon, to make managing multiple aliases easier.
aliases = ugsub(aliases, "%s*;$", "")
for alias_spec in gsplit(aliases, "%s*;%s*") do
local alias_spec_parts = split(alias_spec, "%s*:%s*")
if #alias_spec_parts ~= 2 then
error(("Alias spec '%s' should have one colon in it"):format(alias_spec))
end
local dest, sources = unpack(alias_spec_parts)
sources = split(sources, "%s*,%s*")
local saw_source = nil
for _, source in ipairs(sources) do
if source:match("^%d+$") then
source = tonumber(source)
end
if args[source] then
if saw_source == nil then
saw_source = source
else
error(("|%s= and |%s= are aliases; cannot specify a value for both"):format(saw_source, source))
end
end
end
if saw_source then
if args[dest] then
error(("|%s= is an alias of |%s=; cannot specify a value for both"):format(saw_source, dest))
end
args[dest] = args[saw_source]
-- Wipe out the original after copying. This important in case of a param that has general significance
-- but has been redefined (e.g. {{quote-av}} redefines number= for the episode number, and
-- {{quote-journal}} redefines title= for the chapter= (article). It's also important due to unhandled
-- parameter checking.
args[saw_source] = nil
alias_map[dest] = saw_source
end
end
end
-- Process error_if. The value of `error_if` is a comma-separated list of parameter names to throw an error if seen
-- in parent_args (they are params we overwrite in the direct args).
local error_ifs = ine(direct_args.error_if)
if error_ifs then
for error_if in gsplit(error_ifs, "%s*,%s*") do
if ine(parent_args[error_if]) then
error(
("Cannot specify a value |%s=%s as it would be overwritten or ignored"):format(
error_if,
ine(parent_args[error_if])
)
)
end
end
end
for pname, param in pairs(direct_args) do
-- ignore control params
if pname ~= "ignore" and pname ~= "alias" and pname ~= "error_if" and pname ~= "noroman" then
args[pname] = ine(param)
end
end
return args, alias_map, other_controls
end
local function get_args(frame_args, parent_args, require_lang)
-- FIXME: We are processing arguments twice, once in clone_args() and then again in [[Module:parameters]]. This is
-- wasteful of memory.
local cloned_args, alias_map, other_controls = clone_args(frame_args, parent_args)
local deprecated = ine(parent_args.lang)
local alias_of_t = {alias_of = "t"}
local boolean = {type = "boolean"}
local language_sublist = {type = "language", sublist = true}
local list_allow_holes = {list = true, allow_holes = true}
local script = {type = "script"}
-- First, the "single" params that don't have FOO2 or FOOn versions.
local params = {
[deprecated and "lang" or 1] = {required = require_lang, type = "language", sublist = true, default = "und"},
["lang2"] = language_sublist,
["newversion"] = true,
["author"] = list_allow_holes,
["2ndauthor"] = true,
["trans-author"] = list_allow_holes,
["authorlink"] = list_allow_holes,
["2ndauthorlink"] = true,
["trans-authorlink"] = list_allow_holes,
["first"] = list_allow_holes,
["2ndfirst"] = true,
["trans-first"] = list_allow_holes,
["last"] = list_allow_holes,
["2ndlast"] = true,
["trans-last"] = list_allow_holes,
["nocat"] = boolean,
["nocolon"] = boolean,
-- quote params
text = true,
passage = {alias_of = "text"},
tr = true,
transliteration = {alias_of = "tr"},
ts = true,
transcription = {alias_of = "ts"},
norm = true,
normalization = {alias_of = "norm"},
sc = script,
normsc = script,
sort = true,
subst = true,
footer = true,
lit = true,
t = true,
translation = alias_of_t,
gloss = alias_of_t,
lb = true,
brackets = boolean,
-- original quote params
origtext = true,
origtr = true,
origts = true,
orignorm = true,
origsc = script,
orignormsc = script,
origsubst = true,
origlb = true,
usenodot = boolean,
nodot = boolean,
inline = boolean,
asquote = boolean,
ascite = boolean,
}
-- Most params have PARAM2 variants for use with `newversion`. FIXME: We should generalize this to
-- allow PARAMN variants for any N.
local function add_with_2(param, value)
params[param] = value
params[param .. "2"] = value
end
local function alias_with_2(alias, canon)
params[alias] = {alias_of = canon}
params[alias .. "2"] = {alias_of = canon .. "2"}
end
for _, param12 in ipairs{
"worklang",
"termlang",
"origlang",
"origworklang"
} do
add_with_2(param12, language_sublist)
end
-- Then the newversion params (which have FOO2 versions).
for _, param12 in ipairs{
-- author-like params; author params themselves are either list params (author=, last=, etc.) or single params
-- (2ndauthor=, 2ndlast=, etc.)
"coauthors",
"quotee",
"tlr",
"editor",
"editors",
"mainauthor",
"compiler",
"compilers",
"director",
"directors",
"lyricist",
"lyrics-translator",
"composer",
"role",
"actor",
"artist",
"feat",
-- author control params
"default-authorlabel",
"authorlabel",
-- title
"title",
"trans-title",
"series",
"seriesvolume",
"notitle",
-- entry
"entry",
"entryurl",
"trans-entry",
-- chapter
"chapter",
"chapterurl",
"chapter_number",
"chapter_plain",
"chapter_series",
"chapter_seriesvolume",
"trans-chapter",
"chapter_tlr",
-- section
"section",
"sectionurl",
"section_number",
"section_plain",
"section_series",
"section_seriesvolume",
"trans-section",
-- other video-game params
"system",
"scene",
"level",
-- URL
"url",
"urls",
"archiveurl",
-- edition
"edition",
"edition_plain",
-- ID params
"bibcode",
"doi",
"isbn",
"issn",
"jstor",
"lccn",
"oclc",
"ol",
"pmid",
"pmcid",
"ssrn",
"urn",
"id",
-- misc date params; most date params handled below
"archivedate",
"accessdate",
"nodate",
-- numeric params handled below
-- other params
"type",
"genre",
"format",
"medium",
"others",
"quoted_in",
"location",
"publisher",
"original",
"by",
"deriv",
"note",
"note_plain",
"other",
"source",
"platform",
} do
add_with_2(param12, true)
end
-- Then the aliases of newversion params (which have FOO2 versions).
for _, param12_aliased in ipairs{
{"role", "roles"},
{"role", "speaker"},
{"tlr", "tlrs"},
{"tlr", "translator"},
{"tlr", "translators"},
{"chapter_tlr", "chapter_tlrs"},
{"chapter_tlr", "chapter_translator"},
{"chapter_tlr", "chapter_translators"},
{"doi", "DOI"},
{"isbn", "ISBN"},
{"issn", "ISSN"},
{"jstor", "JSTOR"},
{"lccn", "LCCN"},
{"oclc", "OCLC"},
{"ol", "OL"},
{"pmid", "PMID"},
{"pmcid", "PMCID"},
{"ssrn", "SSRN"},
{"urn", "URN"},
} do
local canon, alias = unpack(param12_aliased)
alias_with_2(alias, canon)
end
-- Then the date params.
for _, datelike in ipairs{{"", ""}, {"orig", ""}, {"", "_published"}} do
local pref, suf = unpack(datelike)
for _, arg in ipairs{"date", "year", "month", "start_date", "start_year", "start_month"} do
add_with_2(pref .. arg .. suf, true)
end
end
local numeric_param_suffixes = {"", "s", "_plain", "url", "_prefix"}
-- Then the numeric params.
for _, numeric in ipairs{"volume", "issue", "number", "line", "page", "column"} do
for _, suf in ipairs(numeric_param_suffixes) do
add_with_2(numeric .. suf, true)
end
end
-- And the aliases of numeric params.
for _, numeric_aliased in ipairs{{"volume", "vol"}} do
local canon, alias = unpack(numeric_aliased)
for _, suf in ipairs(numeric_param_suffixes) do
alias_with_2(alias .. suf, canon .. suf)
end
end
return process_params(cloned_args, params), alias_map, other_controls
end
local function get_origtext_params(args)
local origtext, origtextlang, origsc, orignormsc
if args.origtext then
-- Wiktionary language codes have at least two lowercase letters followed possibly by lowercase letters and/or
-- hyphens (there are more restrictions but this is close enough). Also check for nonstandard Latin etymology
-- language codes (e.g. VL. or LL.). (There used to be more nonstandard codes but they have all been
-- eliminated.)
origtextlang, origtext = args.origtext:match("^(%l%l[%l-]*):([^ ].*)$")
if not origtextlang then
-- Special hack for Latin variants, which can have nonstandard etym codes, e.g. VL., LL.
origtextlang, origtext = args.origtext:match("^(%uL%.):([^ ].*)$")
end
if not origtextlang then
error("origtext= should begin with a language code prefix")
end
origtextlang = get_lang(origtextlang, nil, "allow etym") or
error("origtext= should begin with a language code prefix")
origsc = args.origsc
orignormsc = args.orignormsc
else
for _, noparam in ipairs{"origtr", "origts", "origsc", "orignorm", "orignormsc", "origsubst", "origlb"} do
if args[noparam] then
error(("Cannot specify %s= without origtext="):format(noparam))
end
end
end
return origtext, origtextlang, origsc, orignormsc
end
local function get_quote(args, is_cite)
local text = args.text
local gloss = args.t
local tr = args.tr
local ts = args.ts
local norm = args.norm
local sc = args.sc
local normsc = args.normsc
-- Fetch original-text parameters.
local origtext, origtextlang, origsc, orignormsc = get_origtext_params(args)
-- If any quote-related args are present, display the actual quote; otherwise, display nothing.
if text or gloss or tr or ts or norm or args.origtext then
-- Pass "und" here rather than cause an error; there will be an error on mainspace, Citations, etc. pages
-- in any case in source() if the language is omitted.
local lang = get_first_lang(args[1] or args.lang)
local termlang = args.termlang and get_first_lang(args.termlang) or lang
local usex_data = {
lang = lang,
termlang = termlang,
usex = text,
sc = sc,
translation = gloss,
normalization = norm,
normsc = normsc,
transliteration = tr,
transcription = ts,
brackets = args.brackets,
subst = args.subst,
lit = args.lit,
footer = args.footer,
qq = parse_and_format_labels(args.lb, lang),
quote = "quote-meta",
orig = origtext,
origlang = origtextlang,
origsc = origsc,
orignorm = args.orignorm,
orignormsc = orignormsc,
origtr = args.origtr,
origts = args.origts,
origsubst = args.origsubst,
origqq = parse_and_format_labels(args.origlb, lang),
noreq = args.noreq,
nocat = is_cite or args.nocat,
}
if args.inline then
-- don't let usex format the footer, otherwise it gets inlined with the rest of the quoted text
usex_data.footer = nil
usex_data.inline = 1
text = format_usex(usex_data)
if text then
text = " “" .. text .. "”"
else
text = ""
end
if args.footer then
text = text .. "<dl><dd>" .. args.footer .. "</dd></dl>"
end
else
text = "<dl><dd>" .. format_usex(usex_data) .. "</dd></dl>"
end
elseif args.footer then
text = "<dl><dd>" .. args.footer .. "</dd></dl>"
end
return text
end
-- External interface, meant to be called from a template. Replaces {{quote-meta}} and meant to be the primary
-- interface for {{quote-*}} templates.
function export.quote_t(frame)
local args, alias_map, other_controls = get_args(frame.args, frame:getParent().args, "require_lang")
if args.ascite then
return export.cite_t(frame)
end
return show_quote(args, alias_map, other_controls)
end
function show_quote(args, alias_map, other_controls)
local parts = {}
insert(parts, '<div class="citation-whole"><span class="cited-source">')
insert(parts, export.source(args, alias_map, nil, other_controls))
insert(parts, "</span>")
insert(parts, get_quote(args))
insert(parts, "</div>")
local retval = concat(parts)
return deprecated and frame:expandTemplate({
title = "check deprecated lang param usage",
args = {retval, lang = args.lang},
}) or retval
end
-- External interface, meant to be called from a template. Replaces {{cite-meta}} and meant to be the primary
-- interface for {{cite-*}} templates.
function export.cite_t(frame)
local parent_args = {}
for k, v in pairs(frame:getParent().args) do
parent_args[k] = v
end
-- use "und" as lang if none provided
if parent_args[1] == nil then
parent_args[1] = "und"
end
local args, alias_map, other_controls = get_args(frame.args, parent_args)
if args.asquote then
return show_quote(args, alias_map, other_controls)
end
return show_cite(args, alias_map, other_controls)
end
function show_cite(args, alias_map, other_controls)
local parts = {}
-- don't nag for translations
if args.text and not args.t then
args.noreq = 1
end
local len_visible = args.text and ulen((args.text:gsub("<[^<>]+>", ""))) or 0
if len_visible == 0 then
if not args.t or args.t == "-" then
args.nocolon = true
end
elseif args.inline == nil then
args.inline = not (
args.block_text
or len_visible > 300
or (args.t and not args.t == "-" and len_visible < 80)
or string.match(args.text, "<br>")
)
end
insert(parts, '<span class="citation-whole"><span class="cited-source">')
insert(parts, export.source(args, alias_map, "format_as_cite", other_controls))
insert(parts, "</span>")
insert(parts, get_quote(args, "is_cite"))
insert(parts, "</span>")
local retval = concat(parts)
return deprecated
and frame:expandTemplate({
title = "check deprecated lang param usage",
args = {retval, lang = args.lang},
})
or retval
end
-- External interface, meant to be called from a template.
function export.call_quote_template(frame)
return export.call_template(frame)
end
-- External interface, for calling a template with overloaded parameters.
function export.overload(frame)
local iargs, overloaded_args = process_params(frame.args, {
[1] = {required = true}
}, true)
local parent_args = frame:getParent().args
for k, v in pairs(parent_args) do
overloaded_args[k] = v
end
return frame:expandTemplate{title = iargs[1], args = overloaded_args}
end
-- External interface, meant to be called from a template.
function export.call_template(frame)
local parameter_sublist = {type = "parameter", sublist = true}
local iargs, other_direct_args = process_params(frame.args, {
["template"] = true,
["textparam"] = parameter_sublist,
["pageparam"] = parameter_sublist,
["propagateparams"] = parameter_sublist,
["allowparams"] = {sublist = true}, -- Doesn't use type = "parameter", because any that end in :list get processed differently.
}, true)
local function fetch_param(source, params)
for _, param in ipairs(params) do
if source[param] then
return source[param]
end
end
return nil
end
local params = {
["text"] = true,
["passage"] = true,
["footer"] = true, -- always propagates, but gets special formatting
}
-- paramaters that can be used during template declaration or included in template calls
-- if the template is called with param=- it will set any declared value to nil
local always_propagate = {
["brackets"] = true,
["usenodot"] = true,
["nodot"] = true,
["ascite"] = true,
["asquote"] = true,
}
for k,v in pairs(always_propagate) do
params[k] = v
end
local textparam = iargs.textparam or {}
for _, param in ipairs(textparam) do
params[param] = true
end
local pageparam = iargs.pageparam or {}
local pageparam1 = pageparam[1]
if pageparam1 ~= nil then
params["page"], params["pages"] = true, true
for _, param in ipairs(pageparam) do
params[param] = true
end
end
local allowparams, allow_all, list = iargs.allowparams, false
if allowparams ~= nil then
for _, allow in ipairs(allowparams) do
local param = allow:match("^(.*):list$")
if param then
if list == nil then
list = {list = true}
end
params[scribunto_parameter_key(param)] = list
elseif allow == "*" then
track("no parameter checking")
allow_all = true
else
params[scribunto_parameter_key(allow)] = true
end
end
else
local parent = frame:getParent()
local template_name = parent:getTitle()
local template_title = new_title(template_name)
local content = template_title:getContent()
local allowed_params, seen = {}, {}
-- Detect all params used by the parent template. param:get_name() takes the
-- parent frame arg table as an argument so that preprocessing will take
-- them into account, since it will matter if the name contains another
-- parameter (e.g. the outer param in "{{{foo{{{bar}}}baz}}}" will change
-- depending on the value for bar=). `seen` memoizes results based on the
-- raw parameter text (which is stored as a string in the parameter object),
-- which avoids unnecessary param:get_name() calls, which are non-trivial.
for param in find_parameters(content) do
local raw = param.raw
if not seen[raw] then
allow = param:get_name(template_args)
params[scribunto_parameter_key(allow)] = true
seen[raw] = true
end
end
end
local propagateparams = iargs.propagateparams or {}
for _, param in ipairs(propagateparams) do
params[param] = true
end
local parent_args = frame:getParent().args
local args = process_params(parent_args, params, allow_all)
parent_args = shallow_copy(parent_args)
if textparam[1] ~= "-" then
other_direct_args.passage = args.text or args.passage or fetch_param(args, textparam)
end
if not (pageparam1 == nil or pageparam1 == "-") then
other_direct_args.page = fetch_param(args, pageparam) or args.page or other_direct_args.page or nil
other_direct_args.pages = args.pages or other_direct_args.pages or nil
if other_direct_args.page == "-" then
other_direct_args.page = nil
end
if other_direct_args.pages == "-" then
other_direct_args.pages = nil
end
end
if args.footer then
other_direct_args.footer = frame:expandTemplate{title = "small", args = {args.footer}}
end
for param, _ in pairs(always_propagate) do
if args[param] == "-" then
other_direct_args[param] = nil
else
other_direct_args[param] = args[param] or other_direct_args[param] or nil
end
end
-- authorlink=- can be used to prevent copying of author= to authorlink= but we don't want to propagate this to
-- the actual {{quote-*}} code.
if other_direct_args.authorlink == "-" then
other_direct_args.authorlink = nil
end
for _, param in ipairs(propagateparams) do
if args[param] then
other_direct_args[param] = args[param]
end
end
return frame:expandTemplate{title = iargs.template or "quote-book", args = other_direct_args}
end
local paramdoc_param_replacements = {
passage = {
param_with_synonym = "<<synonym>>, {{para|text}}, or {{para|passage}}",
param_no_synonym = "{{para|text}} or {{para|passage}}",
text = [=[
* <<params>> – the passage to be quoted.]=],
},
page = {
param_with_synonym = "<<synonym>> or {{para|page}}, or {{para|pages}}",
param_no_synonym = "{{para|page}} or {{para|pages}}",
text = [=[
* <<params>> – '''mandatory in some cases''': the page number(s) quoted from. When quoting a range of pages, note the following:
** Separate the first and last pages of the range with an [[en dash]], like this: {{para|pages|10–11}}.
** You must also use {{para|pageref}} to indicate the page to be linked to (usually the page on which the Wiktionary entry appears).
: This parameter must be specified to have the template link to the online version of the work.]=],
},
page_with_roman_preface = {
param_with_synonym = {"inherit", "page"},
param_no_synonym = {"inherit", "page"},
text = [=[
* <<params>> – '''mandatory in some cases''': the page number(s) quoted from. If quoting from the preface, specify the page number(s) in lowercase Roman numerals. When quoting a range of pages, note the following:
** Separate the first and last page number of the range with an [[en dash]], like this: {{para|pages|10–11}} or {{para|pages|iii–iv}}.
** You must also use {{para|pageref}} to indicate the page to be linked to (usually the page on which the Wiktionary entry appears).
: This parameter must be specified to have the template link to the online version of the work.]=],
},
chapter = {
param_with_synonym = "<<synonym>> or {{para|chapter}}",
param_no_synonym = "{{para|chapter}}",
text = [=[
* <<params>> – the name of the chapter quoted from.]=],
},
roman_chapter = {
param_with_synonym = {"inherit", "chapter"},
param_no_synonym = {"inherit", "chapter"},
text = [=[
* <<params>> – the chapter number quoted from in uppercase Roman numerals.]=],
},
arabic_chapter = {
param_with_synonym = {"inherit", "chapter"},
param_no_synonym = {"inherit", "chapter"},
text = [=[
* <<params>> – the chapter number quoted from in Arabic numerals.]=],
},
trailing_params = {
text = [=[
* {{para|footer}} – a comment on the passage quoted.
* {{para|brackets}} – use {{para|brackets|on}} to surround a quotation with [[bracket#Noun|brackets]]. This indicates that the quotation either contains a mere mention of a term (for example, “some people find the word '''''manoeuvre''''' hard to spell”) rather than an actual use of it (for example, “we need to '''manoeuvre''' carefully to avoid causing upset”), or does not provide an actual instance of a term but provides information about related terms.]=],
},
}
function export.paramdoc(frame)
local parargs = frame:getParent().args
local args = process_params(parargs, {
[1] = true,
})
local text = args[1]
local function do_param_with_optional_synonym(param, text_to_sub, paramtext_synonym, paramtext_no_synonym)
local function sub_param(synonym)
local subbed_paramtext
if synonym then
subbed_paramtext = paramtext_synonym:gsub("<<synonym>>", "{{para|" .. replacement_escape(synonym) .. "}}")
else
subbed_paramtext = paramtext_no_synonym
end
return frame:preprocess((text_to_sub:gsub("<<params>>", replacement_escape(subbed_paramtext))))
end
text = text:gsub("<<" .. pattern_escape(param) .. ">>", function()
return sub_param()
end)
text = text:gsub("<<" .. pattern_escape(param) .. ":(.-)>>", sub_param)
end
local function fetch_text(param_to_replace, key)
local spec = paramdoc_param_replacements[param_to_replace]
local val = spec[key]
if type(val) == "string" then
return val
end
if type(val) == "table" and val[1] == "inherit" then
return fetch_text(val[2], key)
end
error(
"Internal error: Unrecognized value for param '"
.. param_to_replace
.. "', key '"
.. key
.. "': "
.. mw.dumpObject(val)
)
end
for param_to_replace, spec in pairs(paramdoc_param_replacements) do
if not spec.param_no_synonym then
-- Text to substitute directly.
text = text:gsub("<<" .. pattern_escape(param_to_replace) .. ">>", function()
return frame:preprocess(fetch_text(param_to_replace, "text"))
end)
else
do_param_with_optional_synonym(
param_to_replace,
fetch_text(param_to_replace, "text"),
fetch_text(param_to_replace, "param_with_synonym"),
fetch_text(param_to_replace, "param_no_synonym")
)
end
end
-- Remove final newline so template code can add a newline after invocation
text = text:gsub("\n$", "")
return text
end
return export
1r3yeqzh8iva3ja93hg2sofji3nygdt
pecutan
0
13260
344391
333216
2026-05-26T04:01:43Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344391
wikitext
text/x-wiki
==Bahasa Melayu=={{wikipedia}}
===Kata nama===
{{ms-kn}}
# {{lb|ms|fizik}} Kadar perubahan [[halaju]] suatu objek yang bergerak.
# {{lb|ms|Malaysia|pendidikan}} Persediaan dalam meningkatkan prestasi akademik sebagai persiapan menghadapi [[peperiksaan]], terutamanya [[peperiksaan awam]].
:# {{quote-web|ms|url=https://www.hmetro.com.my/mutakhir/2021/02/676801/pecutan-akhir-menjelang-spm-esok-metrotv|title='Pecutan' akhir menjelang SPM esok|date=2021-02-21|work=Harian Metro|passage= "Kami membuat '''pecutan''' dua kali ganda untuk mengulang kaji pelajaran sepanjang tempoh pandemik Covid-19 ini," kata pelajar kembar, Muhd Iman Nazri dan Muhd Amin Nazri yang bakal menduduki peperiksaan Sijil Pelajaran Malaysia (SPM) dari Sekolah Menengah Kebangsaan (SMK) Tambun di sini.}}
===Etimologi===
Daripada {{akhiran|ms|pecut|an}}.
===Sebutan===
* {{dewan|pe|cu|tan}}
* {{IPA|ms|/pə.t͡ʃu.tan/}}
===Tulisan Jawi===
{{ARchar|ڤچوتن}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
0xcjhy6y8pc2v2tlhvk8mogvw3r8vgy
Modul:la-headword
828
13543
344384
226390
2026-05-25T23:49:38Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/88547421|88547421]])
344384
Scribunto
text/plain
-- TODO: handle "-old" subtypes generally, appending "in Old Latin", where terms have additional OL inflections.
local export = {}
local pos_functions = {}
local string_utilities = "Module:string utilities"
local table_module = "Module:table"
local utilities_module = "Module:utilities"
local concat = table.concat
local form_is_empty = require("Module:la-utilities").form_is_empty
local insert = table.insert
local remove = table.remove
local umatch = mw.ustring.match
local lang = require("Module:languages").getByCode("la")
local NAMESPACE = mw.title.getCurrentTitle().nsText
local PAGENAME = mw.loadData("Module:headword/data").pagename
local legal_gender = {
["m"] = true,
["f"] = true,
["n"] = true,
["?"] = true,
["?!"] = true,
}
local declension_to_english = {
["1"] = "pertama",
["2"] = "kedua",
["3"] = "ketiga",
["4"] = "keempat",
["5"] = "kelima",
}
local gender_names = {
["m"] = "maskulin",
["f"] = "feminin",
["n"] = "neuter",
["?"] = "genus tidak diketahui",
["?!"] = "genus belum ditentusahkan",
}
local function deep_equals(...)
deep_equals = require(table_module).deepEquals
return deep_equals(...)
end
local function get_plaintext(...)
get_plaintext = require(utilities_module).get_plaintext
return get_plaintext(...)
end
local function insert_if_not(...)
insert_if_not = require(table_module).insertIfNot
return insert_if_not(...)
end
local function invert(...)
invert = require(table_module).invert
return invert(...)
end
local function keys_to_list(...)
keys_to_list = require(table_module).keysToList
return keys_to_list(...)
end
local function pattern_escape(...)
pattern_escape = require(string_utilities).pattern_escape
return pattern_escape(...)
end
local function serial_comma_join(...)
serial_comma_join = require(table_module).serialCommaJoin
return serial_comma_join(...)
end
local function split(...)
split = require(string_utilities).split
return split(...)
end
local function ulower(...)
ulower = require(string_utilities).lower
return ulower(...)
end
local function format(array, concatenater)
if #array == 0 then
return ""
end
local concatenated = concat(array, concatenater)
if concatenated == "" then
return ""
elseif concatenated:sub(-1) == "'" then
concatenated = concatenated .. " "
end
return "; ''" .. concatenated .. "''"
end
local function glossary_link(anchor, text)
text = text or anchor
return "[[Lampiran:Glosari#" .. anchor .. "|" .. text .. "]]"
end
local function make_link(page, display, face, accel)
return require("Module:links").full_link({term = page, alt = display, lang = lang, accel = accel}, face)
end
-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
local iargs = require("Module:parameters").process(frame.args, {
[1] = {required = true},
["def"] = true,
["suff_type"] = true,
})
local args = frame:getParent().args
local poscat = iargs[1]
local def = iargs.def
local suff_type = iargs.suff_type
local postype = nil
if suff_type then
postype = poscat .. '-' .. suff_type
else
postype = poscat
end
local data = {lang = lang, categories = {}, heads = {}, genders = {}, inflections = {}}
local infl_classes = {}
local title = {}
local postscript = {}
if poscat == "akhiran" then
insert_if_not(data.categories, "Akhiran membentuk " .. suff_type .. "")
end
if pos_functions[postype] then
local new_poscat = pos_functions[postype](def, args, data, infl_classes, title, postscript)
if new_poscat then
poscat = new_poscat
end
end
data.pos_category = poscat
postscript = concat(postscript, ", ")
return
require("Module:headword").full_headword(data)
.. format(infl_classes, "/")
.. format(title, ", ")
.. (postscript ~= "" and " (" .. postscript .. ")" or "")
end
local function process_num_type(numtype, categories)
if numtype == "card" then
insert_if_not(categories, "Nombor kardinal bahasa Latin")
elseif numtype == "ord" then
insert_if_not(categories, "Nombor ordinal bahasa Latin")
elseif numtype == "frac" then
insert_if_not(categories, "Nombor pecahan bahasa Latin")
elseif numtype == "dist" then
insert_if_not(categories, "Nombor agihan bahasa Latin")
elseif numtype == "mul" then
insert_if_not(categories, "Nombor perkalian bahasa Latin")
elseif numtype == "coll" then
insert_if_not(categories, "Nombor kolektif bahasa Latin")
elseif numtype then
error("Unrecognized numeral type '" .. numtype .. "'")
end
end
local function normalize_derivation(deriv, anchor, text)
if not deriv then
return nil
end
local deriv1 = deriv[1]
if not deriv1 or deriv1 == "-" then
return deriv1
end
deriv.label = glossary_link(anchor, text)
return deriv
end
local function derivation(data, decldata, arg, anchor, text)
local der = normalize_derivation(decldata[arg], anchor, text)
if der and der ~= "-" then
insert(data.inflections, der)
end
end
local function nouns(pos, def, args, data, infl_classes, title)
local is_num = pos == "kata bilangan"
local is_pn = false
if pos == "kata nama khas" then
is_pn = true
pos = "kata nama"
end
local decldata = require("Module:la-nominal").do_generate_noun_forms(args, pos, "headword", def, is_num)
local lemma = decldata.overriding_lemma
-- TODO: modify the headword line if the slot isn't the expected one.
if #lemma == 0 then
for slot in require("Module:la-nominal").iter_potential_noun_lemma_slots() do
local potential_lemma = decldata.forms["linked_" .. slot]
if not form_is_empty(potential_lemma) then
if decldata.unattested[slot] then
potential_lemma = "*" .. potential_lemma
end
lemma = potential_lemma
break
end
end
end
data.heads = lemma
-- Since we always set data.heads to the lemma and specification of the lemma is mandatory in {{la-noun}}, there aren't
-- really any redundant heads.
data.no_redundant_head_cat = true
data.id = decldata.id
local genders = decldata.overriding_genders
if #genders == 0 then
if decldata.gender then
genders = {ulower(decldata.gender)}
elseif not is_num then
error("No gender explicitly specified in headword template using g=, and can't infer gender from lemma spec")
end
end
local categories = data.categories
if is_num then
process_num_type(decldata.num_type, categories)
end
if decldata.indecl then
insert(data.inflections, {label = glossary_link("indeclinable")})
insert_if_not(categories, decldata.pos .. " tegar bahasa Latin")
for _, g in ipairs(genders) do
local gender = g:match("^(.[\128-\191]*)%-[sp]$")
if not gender then
gender = g
end
if not legal_gender[gender] then
error("Gender “" .. gender .. "” is not a valid Latin gender.")
end
insert(data.genders, g)
insert_if_not(categories, decldata.pos .. " tegar " .. gender_names[gender] .. " bahasa Latin")
end
else
local is_irreg = false
local is_indecl = false
local is_decl = false
local has_multiple_decls = false
local has_multiple_variants = false
-- flatten declension specs
local decls = {}
for _, g in ipairs(genders) do
if not legal_gender[g] then
error("Gender “" .. g .. "” is not a valid Latin gender.")
elseif decldata.num == "pl" then
g = g .. "-p"
elseif decldata.num == "sg" then
g = g .. "-s"
end
insert(data.genders, g)
end
local function process_decl(decl_list, props)
local headword_decl = props.headword_decl
-- skip adjectival declensions
if headword_decl:match("+$") then
return
elseif props.decl == "irreg" then
is_irreg = true
headword_decl = headword_decl:match("^irreg/(.*)$") or headword_decl
local irreg_decls = split(headword_decl, ",")
if #irreg_decls > 1 then
has_multiple_decls = true
end
for _, d in ipairs(irreg_decls) do
if d == "indecl" or d == "0" then
is_indecl = true
else
is_decl = true
end
insert_if_not(decl_list, d)
end
else
if headword_decl == "indecl" or headword_decl == "0" then
is_indecl = true
else
is_decl = true
end
insert_if_not(decl_list, headword_decl)
end
end
for _, props in ipairs(decldata.propses) do
if props.headword_decl then
process_decl(decls, props)
else
local alternant_decls = {}
for _, alternant in ipairs(props) do
for _, single_props in ipairs(alternant) do
process_decl(alternant_decls, single_props)
end
end
if #alternant_decls > 1 then
has_multiple_decls = true
elseif #decls > 1 then
has_multiple_variants = true
end
for _, d in ipairs(alternant_decls) do
insert_if_not(decls, d)
end
end
end
if is_indecl and is_decl then
has_multiple_decls = true
end
if has_multiple_decls then
insert_if_not(categories, decldata.pos .. " dengan berbilang tasrif bahasa Latin")
end
if has_multiple_variants then
insert_if_not(categories, decldata.pos .. " dengan berbilang kelainan tasrif tunggal bahasa Latin")
end
if is_irreg then
insert(title, glossary_link("tak nalar"))
insert_if_not(categories, decldata.pos .. " tak nalar bahasa Latin")
for _, g in ipairs(genders) do
insert_if_not(categories, "Latin " .. gender_names[g] .. " irregular " .. decldata.pos)
end
end
if is_indecl then
if is_decl then
insert(title, glossary_link("tegar"))
else
insert(data.inflections, {label = glossary_link("tegar")})
end
insert_if_not(categories, decldata.pos .. " tegar bahasa Latin")
for _, g in ipairs(genders) do
insert_if_not(categories, decldata.pos .. " tegar " .. gender_names[g] .. " bahasa Latin")
end
end
if #decls > 1 then
insert(title, "variously declined")
end
for _, decl in ipairs(decls) do
if not (decl == "0" or decl == "indecl" or decl == "sgpl" or decl == "irreg") then
local decl_class = declension_to_english[decl]
if not decl_class then
error("Internal error: declension '" .. decl .. "' not recognized")
end
insert(title, "[[Lampiran:Tasrif " .. decl_class .. " bahasa Latin|tasrif " .. decl_class .. "")
insert_if_not(categories, decldata.pos .. " tasrif " .. decl_class .. " bahasa Latin")
for _, g in ipairs(genders) do
insert_if_not(categories, decldata.pos .. " " .. gender_names[g] .. " bahasa Latin dalam tasrif " .. decl_class)
end
end
end
local lemma_num = decldata.num == "pl" and "pl" or "sg"
if NAMESPACE == "Rekonstruksi" then
-- For reconstructed nouns:
if data.genders[1] == 'n' and lemma_num == 'sg' then
-- singular neuter nouns give a plural
local pl = decldata.forms["nom_pl"]
if pl and pl ~= "" and #pl > 0 then
pl.label = "jamak"
insert(data.inflections, pl)
end
else
-- all others give an oblique
local obl = decldata.forms["acc_" .. lemma_num]
if obl and obl ~= "" and #obl > 0 then
obl.label = "oblique"
insert(data.inflections, obl)
end
end
else
local gen = decldata.forms["gen_" .. lemma_num]
if (decldata.unattested["gen_" .. lemma_num]) then
gen[1] = '*' .. gen[1]
data.nolink = true
end
if gen and gen ~= "" and gen ~= "—" and #gen > 0 then
if is_decl then
-- Skip displaying the genitive for nouns that are only
-- indeclinable. But we do display it for nouns like Abrahām
-- and Ādām that can be either indeclinable or declined.
gen.label = "genitif"
insert(data.inflections, gen)
end
else
insert(data.inflections, {label = "tiada genitif"})
insert_if_not(categories, decldata.pos .. " bahasa Latin dengan ketiadaan bentuk mufrad genetif")
end
end
end
derivation(data, decldata, "m", "maskulin")
derivation(data, decldata, "f", "feminin")
derivation(data, decldata, "n", "neuter")
derivation(data, decldata, "adj", "berhubungan", "kata sifat berhubungan")
derivation(data, decldata, "dim", "diminutif")
derivation(data, decldata, "aug", "augmentatif")
for _, cat in ipairs(decldata.categories) do
insert_if_not(categories, cat)
end
for _, cat in ipairs(decldata.cat) do
insert_if_not(categories, cat .. " bahasa Latin")
end
return is_pn and decldata.pos == "kata nama" and "kata nama khas" or decldata.pos
end
pos_functions["kata nama"] = function(def, args, data, infl_classes, title)
return nouns("kata nama", def, args, data, infl_classes, title)
end
pos_functions["kata nama khas"] = function(def, args, data, infl_classes, title)
return nouns("kata nama khas", def, args, data, infl_classes, title)
end
pos_functions["kata nama akhiran"] = function(def, args, data, infl_classes, title)
return nouns("akhiran", def, args, data, infl_classes, title)
end
pos_functions["kata nama bilangan"] = function(def, args, data, infl_classes, title)
return nouns("kata bilangan", def, args, data, infl_classes, title)
end
function export.verb_title(title, typeinfo, lemma_forms)
local conj = typeinfo.conj
local irreg_processing = typeinfo.irreg
local subtypes = typeinfo.subtypes
local first_lemma = ""
if #lemma_forms > 0 then
first_lemma = require("Module:links").remove_links(lemma_forms[1])
end
if conj == "1st" then
insert(title, "[[Appendix:Latin first conjugation|first conjugation]]")
elseif conj == "2nd" then
insert(title, "[[Appendix:Latin second conjugation|second conjugation]]")
elseif conj == "3rd" then
insert(title, "[[Appendix:Latin third conjugation|third conjugation]]")
elseif conj == "3rd-io" then
insert(title, ("[[Appendix:Latin third conjugation|third (%s variant) conjugation]]"):format(make_link(nil, "-iō", "term")))
elseif conj == "3rd/4th" then
insert(title, ("[[Appendix:Latin third conjugation|third (%s variant)]] / [[Appendix:Latin fourth conjugation|fourth conjugation]]"):format(make_link(nil, "-iō", "term")))
elseif conj == "4th" then
insert(title, "[[Appendix:Latin fourth conjugation|fourth conjugation]]")
elseif conj == "irreg" then -- sum
insert(title, "[[Appendix:Latin irregular verbs|irregular conjugation]]")
end
if subtypes.highlydef then -- āiō, inquam
insert(title, "highly [[defective verb#English|defective]]")
end
if subtypes.suppl then -- sum, volō
insert(title, "[[suppletive#English|suppletive]]")
end
if subtypes["3only"] then -- decet
insert(title, "[[third person#English|third person]]-only")
elseif subtypes.impers then -- decet, advesperāscit (also nopass)
insert(title, "[[impersonal verb#English|impersonal]]")
end
if subtypes.depon then -- dēmōlior, calvor (also noperf)
insert(title, "[[deponent#English|deponent]]")
end
if subtypes.perfaspres then -- meminī, ōdī
insert(title, "no [[present tense#English|present]] stem")
-- If semidepon is set, only the active forms are affected.
local voice = subtypes.semidepon and "[[active voice#English|active]] " or ""
insert(title, ("[[perfect tense#English|perfect]] %sforms have [[present tense#English|present]] %smeaning"):format(voice, voice))
-- Clarify that deponency can only apply to the perfect.
if subtypes.semidepon then -- ōdī
insert(title, "[[deponent#English|deponent]] in the [[perfect tense#English|perfect]]")
end
if subtypes.optsemidepon then
insert(title, "optionally [[deponent#English|deponent]] in the [[perfect tense#English|perfect]]")
end
else
if subtypes.semidepon then -- fīdō, gaudeō
insert(title, "[[semi-deponent#English|semi-deponent]]")
end
if subtypes.optsemidepon then -- audeō, placeō, soleō, pudeō
insert(title, "optionally [[semi-deponent#English|semi-deponent]]")
end
end
if subtypes.imponly then -- cedo, apage
insert(title, "[[imperative mood#English|imperative]]-only")
end
if subtypes.nopass then -- coacēscō
insert(title, "no [[passive voice#English|passive]]")
end
local stems = {}
if subtypes.nopres then -- coepī; perfaspres already handles this above
insert(stems, "[[present tense#English|present]]")
end
if subtypes.noperf then
insert(stems, "[[perfect tense#English|perfect]]")
end
if subtypes.nosup or subtypes.supfutractvonly then
insert(stems, "[[supine#English|supine]]")
end
if #stems > 0 then
local extra = subtypes.supfutractvonly and " except in the [[future tense#English|future]] [[active voice#English|active]] [[participle#English|participle]]"
insert(title, ("no %s stem%s%s"):format(serial_comma_join(stems, {conj = "or"}), #stems > 1 and "s" or "", extra or ""))
end
if subtypes.nofutr then -- soleō
insert(title, "no [[future tense#English|future]]")
end
if subtypes.pass3only then -- praefundō
insert(title, "[[third person#English|third person]]-only in the [[passive voice#English|passive]]")
elseif subtypes.passimpers then -- abambulō
local msg = "[[impersonal verb#English|impersonal]] in the [[passive voice#English|passive]]"
if subtypes.passimpersold then -- possum
msg = msg .. " in [[Old Latin]]"
end
insert(title, msg)
end
if subtypes.noimp then -- volō
insert(title, "no [[imperative mood#English|imperative]]")
end
if irreg_processing and umatch(first_lemma, "d[īū]cō$") then -- dīcō
insert(title, "[[Appendix:Latin irregular verbs|irregular]] short [[imperative mood#English|imperative]]")
end
if subtypes.nofutractvptc and not subtypes.nosup then -- fīō
insert(title, "no [[future tense#English|future]] [[active voice#English|active]] [[participle#English|participle]]")
end
if not (subtypes.nopres or subtypes.perfaspres or subtypes.imponly) then
if subtypes.noinf then -- inquam
insert(title, "no [[infinitive#English|infinitive]]")
end
if subtypes.noger then -- libet
insert(title, "no [[gerund#English|gerund]]")
end
end
if subtypes.shorta then -- dō
insert(title, ("[[Appendix:Latin irregular verbs|irregular]] short %s in most forms"):format(make_link(nil, "ă", "term")))
end
if irreg_processing then
if first_lemma:match("edō$") then -- edō
insert(title, "[[Appendix:Latin irregular verbs|irregular]] alternative forms")
elseif first_lemma:match("fīō$") then -- fīō
insert(title, "[[Appendix:Latin irregular verbs|irregular]] long " .. make_link(nil, "ī", "term"))
end
end
end
pos_functions["kata kerja"] = function(def, args, data, infl_classes, title)
local m_la_verb = require("Module:la-verb")
local def1, def2
if def then
def1, def2 = def:match("^(.-):(.*)$")
end
local conjdata, typeinfo = m_la_verb.make_data(args, true, def1, def2)
local lemma_forms = conjdata.overriding_lemma
if not lemma_forms or #lemma_forms == 0 then
lemma_forms = m_la_verb.get_lemma_forms(conjdata, true)
end
data.heads = lemma_forms
-- Since we always set data.heads to the lemma and specification of the lemma is mandatory in {{la-verb}}, there aren't
-- really any redundant heads.
data.no_redundant_head_cat = true
data.id = conjdata.id
local perf_only = false
local function insert_inflection(infl, label)
infl.label = label
insert(data.inflections, infl)
end
local inf = m_la_verb.get_valid_forms(conjdata.forms["pres_actv_inf"])
if #inf > 0 then
insert_inflection(inf, "present infinitive")
else
inf = m_la_verb.get_valid_forms(conjdata.forms["perf_actv_inf"])
if #inf > 0 then
perf_only = true
insert_inflection(inf, "perfect infinitive")
end
end
if not perf_only then
local perf = m_la_verb.get_valid_forms(conjdata.forms["1s_perf_actv_indc"])
if #perf == 0 then
perf = m_la_verb.get_valid_forms(conjdata.forms["3s_perf_actv_indc"])
end
if #perf > 0 then
insert_inflection(perf, "perfect active")
end
end
local subtypes = typeinfo.subtypes
if not (subtypes.depon or subtypes.semidepon) then
local sup = m_la_verb.get_valid_forms(conjdata.forms["acc_sup"])
if #sup > 0 then
insert_inflection(sup, "supine")
else
local fap = m_la_verb.get_valid_forms(conjdata.forms["futr_actv_ptc"])
if #fap > 0 then
insert_inflection(fap, "future active participle")
end
end
end
export.verb_title(title, typeinfo, lemma_forms)
end
pos_functions["kata kerja akhiran"] = pos_functions["kata kerja"]
local function attested_form(decldata, index)
local form
if (decldata.unattested[index]) then
form = { { term = '*' .. decldata.forms[index][1], nolink = true } }
else
form = decldata.forms[index]
end
return form
end
local function degree_derivations(comp, sup, data)
local inflections = data.inflections
if not (comp or sup) then
return
elseif (not comp or comp == "-") and (not sup or sup == "-") then
insert(inflections, {label = "not [[Appendix:Glossary#comparative|comparable]]"})
insert_if_not(data.categories, "Latin uncomparable adverbs")
return
elseif comp == "-" then
insert(inflections, {label = "no [[Appendix:Glossary#comparative|comparative]]"})
elseif comp then
insert(inflections, comp)
end
if sup == "-" then
insert(inflections, {label = "no [[Appendix:Glossary#superlative|superlative]]"})
elseif sup then
insert(inflections, sup)
end
end
local function adjectives(pos, def, args, data, infl_classes)
local is_num = pos == "kata bilangan"
local decldata = require("Module:la-nominal").do_generate_adj_forms(args, pos, "headword", nil, def)
local lemma = decldata.overriding_lemma
-- TODO: modify the headword line if the slot isn't the expected one.
if #lemma == 0 then
for slot in require("Module:la-nominal").iter_potential_adj_lemma_slots() do
local potential_lemma = decldata.forms["linked_" .. slot]
if not form_is_empty(potential_lemma) then
if decldata.unattested[slot] then
potential_lemma = "*" .. potential_lemma
end
lemma = potential_lemma
break
end
end
end
data.heads = lemma
-- Since we always set data.heads to the lemma and specification of the lemma is mandatory in {{la-noun}}, there aren't
-- really any redundant heads.
data.no_redundant_head_cat = true
data.id = decldata.id
local categories = data.categories
if is_num then
process_num_type(decldata.num_type, categories)
end
if decldata.num == "pl" then
insert_if_not(categories, "Latin plural-only " .. decldata.pos)
end
if decldata.indecl then
insert(data.inflections, {label = glossary_link("indeclinable")})
if decldata.pos == "partisipel" then
local lemma1 = lemma[1]
if lemma1:sub(-4) == "ndum" then
insert_if_not(categories, "Latin future passive participles")
elseif lemma1:match("um$") then
insert_if_not(categories, "Latin perfect participles")
end
end
else
local lemma_num = decldata.num == "pl" and "pl" or "sg"
local masc = decldata.forms["nom_" .. lemma_num .. "_m"]
local fem = attested_form(decldata, "nom_" .. lemma_num .. "_f")
local neut = attested_form(decldata, "nom_" .. lemma_num .. "_n")
local gen = attested_form(decldata, "gen_" .. lemma_num .. "_m")
local acc = attested_form(decldata, "acc_" .. lemma_num .. "_m")
if decldata.pos == "partisipel" then
local masc1 = masc[1]
if masc1:sub(-5) == "ūrus" then
insert_if_not(categories, "Latin future active participles")
elseif masc1:sub(-4) == "ndus" then
-- FIXME, should rename to "Latin gerundives")
insert_if_not(categories, "Latin future passive participles")
else
local masc1_final2 = masc1:sub(-2)
if masc1_final2 == "us" then
insert_if_not(categories, "Latin perfect participles")
elseif masc1_final2 == "ns" then
insert_if_not(categories, "Latin present participles")
else
error("Unrecognized participle ending: " .. masc1)
end
end
end
-- We display the inflections in three different ways to mimic the
-- old way of doing things:
--
-- 1. If masc and fem are different, show masc, fem and neut.
-- 2. Otherwise, if masc and neut are different, show masc and neut.
-- 3. Otherwise, show masc nominative and masc genitive.
if not form_is_empty(fem) and not deep_equals(masc, fem) then
fem.label = "feminin"
insert(data.inflections, fem)
if not form_is_empty(neut) then
neut.label = "neuter"
insert(data.inflections, neut)
end
elseif not form_is_empty(neut) and not deep_equals(masc, neut) then
neut.label = "neuter"
insert(data.inflections, neut)
elseif not form_is_empty(gen) then
gen.label = "genitif"
insert(data.inflections, gen)
elseif not form_is_empty(acc) then
acc.label = "akusatif"
insert(data.inflections, acc)
end
insert(infl_classes, decldata.title)
end
local comp = normalize_derivation(decldata.comp, "bandingan")
local sup = normalize_derivation(decldata.sup, "superlatif")
degree_derivations(comp, sup, data)
derivation(data, decldata, "adv", "adverba")
for _, cat in ipairs(decldata.categories) do
insert_if_not(categories, cat)
end
for _, cat in ipairs(decldata.cat) do
insert_if_not(categories, cat .. " bahasa Latin")
end
return decldata.pos
end
pos_functions["kata sifat"] = function(def, args, data, infl_classes, title)
return adjectives("kata sifat", def, args, data, infl_classes, title)
end
pos_functions["partisipel"] = function(def, args, data, infl_classes, title)
return adjectives("partisipel", def, args, data, infl_classes, title)
end
pos_functions["penunjuk"] = function(def, args, data, infl_classes, title)
return adjectives("penunjuk", def, args, data, infl_classes, title)
end
pos_functions["kata ganti nama"] = function(def, args, data, infl_classes, title)
return adjectives("kata ganti nama", def, args, data, infl_classes, title)
end
pos_functions["kata sifat akhiran"] = function(def, args, data, infl_classes, title)
return adjectives("akhiran", def, args, data, infl_classes, title)
end
pos_functions["kata sifat bilangan"] = function(def, args, data, infl_classes, title)
return adjectives("kata bilangan", def, args, data, infl_classes, title)
end
pos_functions["adverba"] = function(def, args, data)
local sublist = {sublist = "/"}
args = require("Module:parameters").process(args, {
[1] = {alias_of = "head", list = false},
[2] = {alias_of = "comp"},
[3] = {alias_of = "sup"},
["head"] = {list = true, required = true},
["comp"] = sublist,
["sup"] = sublist,
["adj"] = sublist,
["id"] = true,
})
data.heads = args.head
data.no_redundant_head_cat = true -- since head= is required
data.id = args.id
local comp, sup = args.comp, args.sup
local irreg = false
if comp then
if comp[1] == "-" then
comp = "-"
elseif comp[1] == nil then
comp = nil
else
comp.label = glossary_link("bandingan")
comp = args.comp
irreg = true
end
end
if sup then
if sup[1] == "-" then
sup = "-"
elseif sup[1] == nil then
sup = nil
else
sup.label = glossary_link("superlatif")
sup = args.sup
irreg = true
end
end
local categories = data.categories
if irreg then
insert_if_not(categories, "Adverba tak nalar bahasa Latin")
end
if not (comp or sup) then
local default_comp = {label = glossary_link("bandingan")}
local default_sup = {label = glossary_link("superlatif")}
for _, head in ipairs(args.head) do
local stem = nil
for _, suff in ipairs{"iter", "nter", "ter", "er", "iē", "ē", "rā", "im", "ō"} do
stem = head:match("(.*)" .. pattern_escape(suff) .. "$")
comp_suff, sup_suff = "ius", "issimē"
if stem ~= nil then
if suff == "nter" then
stem = stem .. "nt"
elseif suff == "rā" then
comp_suff = "er" .. comp_suff
sup_suff = "imē"
end
insert(default_comp, stem .. comp_suff)
insert(default_sup, stem .. sup_suff)
break
end
end
if not stem then
error("Unrecognized adverb type, recognized types are “-ē”, “-er”, “-ter”, “-iter”, “-im”, or “-ō”, “-ra” or specify irregular forms or “-” if incomparable.")
end
end
comp = comp or default_comp
sup = sup or default_sup
end
degree_derivations(comp, sup, data)
derivation(data, args, "adj", "kata sifat")
end
pos_functions["kata adverba akhiran"] = pos_functions["adverba"]
local function get_forms(forms)
if #forms == 0 then
return nil
end
local i, attested = 1, false
while true do
local form = forms[i]
if form == nil then
return forms, attested
elseif form == "-" then
remove(forms, i)
else
if not (attested or get_plaintext(form):sub(1, 1) == "*") then
attested = true
end
i = i + 1
end
end
end
local function degree(pos, deg, pos_func, other_pos, other_pos_label, other_deg, other_deg_label, args, data, infl_classes)
local list = {list = true}
args = require("Module:parameters").process(args, {
[1] = {alias_of = "head", list = false},
["head"] = list,
["positif"] = list,
[other_pos] = {sublist = "/"},
[other_deg] = list,
["id"] = true,
})
data.no_redundant_head_cat = #args.head == 0
-- Set default manually so we can tell whether the user specified head=.
if #args.head == 0 then
args.head = {PAGENAME}
end
data.heads = args.head
data.id = args.id
insert(data.inflections, {label = deg})
if pos_func then
pos_func(args, data, infl_classes)
end
local positive, positive_attested = get_forms(args.positive)
if positive then
if not positive_attested then
insert(data.categories, "Latin " .. deg .. "-only " .. pos)
end
if #positive > 0 then
args.positive.label = "positif"
insert(data.inflections, args.positive)
else
insert(data.inflections, {label = "tiada bentuk positif"})
end
end
local other = get_forms(args[other_deg])
if other then
if #other > 0 then
args[other_deg].label = other_deg_label
insert(data.inflections, args[other_deg])
else
insert(data.inflections, {label = "tiada bentuk " .. other_deg_label})
end
end
derivation(data, args, other_pos, other_pos_label)
-- If a lemma, return the primary part of speech ("kata sifat" or
-- "adverba"), so that the term is categorized in "Latin adjectives" or
-- "Latin adverbs". Otherwise, return nothing, so that the term goes in the
-- relevant non-lemma category (e.g. "Latin comparative adjectives"), and
-- into "Latin non-lemma forms".
if positive and not positive_attested then
return pos
end
end
local function comp_adj(args, data, infl_classes)
insert(infl_classes, "[[Appendix:Latin third declension|third declension]]")
local n = {label = "neuter"}
for _, head in ipairs(args.head) do
local neuter = head:gsub("or$", "us")
insert(n, neuter)
end
insert(data.inflections, n)
end
pos_functions["kata sifat bandingan"] = function(def, args, data, infl_classes, title)
return degree("kata sifat", "bandingan", comp_adj, "adv", "adverba", "sup", "superlatif", args, data, infl_classes)
end
pos_functions["adverba bandingan"] = function(def, args, data, infl_classes, title)
return degree("adverba", "bandingan", nil, "adj", "kata sifat", "sup", "superlatif", args, data, infl_classes)
end
local function sup_adj(args, data, infl_classes)
insert(infl_classes, "[[Appendix:Latin first declension|first]]")
insert(infl_classes, "[[Appendix:Latin second declension|second declension]]")
local f, n = {label = "feminine"}, {label = "neuter"}
for _, head in ipairs(args.head) do
local stem = head:gsub("us$", "")
insert(f, stem .. "a")
insert(n, stem .. "um")
end
insert(data.inflections, f)
insert(data.inflections, n)
end
pos_functions["kata sifat superlatif"] = function(def, args, data, infl_classes, title)
return degree("kata sifat", "superlatif", sup_adj, "adv", "adverba", "comp", "bandingan", args, data, infl_classes)
end
pos_functions["adverba superlatif"] = function(def, args, data, infl_classes, title)
return degree("adverba", "superlatif", nil, "adj", "kata sifat", "comp", "bandingan", args, data, infl_classes)
end
local function adpositions(pos, def, args, data, infl_classes, title, postscript)
local cases = invert(require("Module:la-utilities").cases)
args = require("Module:parameters").process(args, {
[1] = {alias_of = "head", list = false},
[2] = {list = true, set = keys_to_list(cases)},
["head"] = {list = true, required = true},
["id"] = true,
})
-- Case names are supplied in numbered arguments, optionally preceded by
-- headwords.
cases = args[2]
for i = 1, #cases do
for j = i + 1, #cases do
if cases[i] == cases[j] then
error("Duplicate case")
end
end
local case = cases[i]
local appendix_link = glossary_link(case)
if i == 1 then
appendix_link = "+ " .. appendix_link
end
insert(postscript, appendix_link)
insert_if_not(data.categories, pos .. " " .. case .. " bahasa Latin")
end
data.heads = args.head
data.no_redundant_head_cat = true -- since head= is required
data.id = args.id
end
pos_functions["kata depan"] = function(...)
return adpositions("kata depan", ...)
end
pos_functions["kata dudi"] = function(...)
return adpositions("kata dudi", ...)
end
pos_functions["gerund"] = function(def, args, data)
args = require("Module:parameters").process(args, {
[1] = {required = true, default = "labōrandum"}, -- headword
[2] = true, -- gerundive
})
data.heads = {args[1]}
data.no_redundant_head_cat = true -- since 1= is required and goes into data.heads
insert(data.inflections, {label = "[[Appendix:Glossary#accusative|accusative]]"})
local stem = args[1]:match("^(.*)um$")
if not stem then
error("Unrecognized gerund ending: " .. stem)
end
if args[2] == "-" then
insert(data.inflections, {label = "no [[Appendix:Glossary#gerundive|gerundive]]"})
else
insert(data.inflections, {[1] = args[2] or stem .. "us", label = "[[Appendix:Glossary#gerundive|gerundive]]"})
end
end
local function non_lemma_forms(def, args, data)
args = require("Module:parameters").process(args, {
[1] = {required = true, default = def}, -- headword or cases
["head"] = {list = true, require_index = true},
["g"] = {list = true},
["id"] = true,
})
local heads = {args[1]}
for _, head in ipairs(args.head) do
insert(heads, head)
end
data.heads = heads
data.no_redundant_head_cat = true -- since 1= is required and goes into data.heads
data.genders = args.g
data.id = args.id
end
pos_functions["bentuk kata nama"] = non_lemma_forms
pos_functions["bentuk kata nama khas"] = non_lemma_forms
pos_functions["bentuk kata ganti nama"] = non_lemma_forms
pos_functions["bentuk kata kerja"] = non_lemma_forms
pos_functions["bentuk gerund"] = non_lemma_forms
pos_functions["bentuk kata sifat"] = non_lemma_forms
pos_functions["bentuk partisipel"] = non_lemma_forms
pos_functions["bentuk penunjuk"] = non_lemma_forms
pos_functions["bentuk kata bilangan"] = non_lemma_forms
pos_functions["bentuk akhiran"] = non_lemma_forms
return export
cjqhcyeynwe362zkj9844huwsemfww2
tunggang agama
0
16706
344397
335596
2026-05-26T04:06:02Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344397
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata kerja===
{{ms-kk}}
# {{lb|ms|agama}} Sengaja menyalahgunakan atau membuat [[tafsiran]] salah terhadap suatu ilmu agama untuk memperoleh keuntungan diri.
:* {{quote-web|ms|title=Komodifikasi agama: Cara untuk raih untung|url=https://harakahdaily.net/index.php/2019/10/11/komodifikasi-agama-cara-untuk-raih-untung/|passage=Secara kasarnya konsep ini adalah proses menjual apa yang boleh dijual bukan menjual apa yang perlu dijual. Atau dengan mudah faham, apa sahaja yang ada nilai komersial, akan diolah hingga boleh menghasilkan keuntungan, sekalipun terpaksa menggunakan atas nama agama. Bahasa mudah yang digunapakai ialah ‘'''menunggang agama'''’ untuk kaut untung.|work=Harakah Daily|date=2019-10-11}}
:* {{quote-web|ms|title=8 Produk ‘Islamik’ Ini Bukti Orang Kita Berniaga Sambil Tunggang Agama. Akhir Zaman!|work=SAYS Seismik|author=Zaidi Aziz|date=2017-02-20|url=https://says.com/my/seismik/tunggang-agama|quote=Dalam ''post'' tersebut, beliau berkata ramai Melayu muslim kini '''menunggang agama''' tanpa rasa bersalah.}}
====Terbitan kata====
* [[penunggang agama]]
===Etimologi===
Daripada {{compound|ms|tunggang|agama}}.
===Sebutan===
* {{dewan|tung|gang|a|ga|ma}}
===Tulisan Jawi===
<big>[[توڠݢڠ اݢام]]</big>
===Pautan luar===
* {{R:PRPM}}
shbv76cxk32nckgsj1w7fzaugiz1law
Modul:la-verb
828
16886
344379
226389
2026-05-25T23:09:05Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/90355872|90355872]]), akan terjemahkan kategori kemudian
344379
Scribunto
text/plain
-- TODO:
-- 1. (DONE) detect_decl_and_subtypes doesn't do anything with perf_stem or supine_stem.
-- 2. (DONE) Should error on bad subtypes.
-- 3. Make sure Google Books link still works.
-- 4. (DONE) Add 4++ that has alternative perfects -īvī/-iī.
-- 5. (DONE) If sup but no perf, allow passive perfect forms.
-- 6. (DONE) Remove no-actv-perf.
-- 7. (DONE) Support plural prefix/suffix and plural passive prefix/suffix
-- 8. Delegate title line generation to [[Module:la-headword]].
-- 9. Automatic forms of slots which depend on the values of other slots should take into account overrides on the other slot:
-- futr_actv_ptc: determines futr_actv_inf and perp_actv_inf
-- perf_pasv_ptc: determines perf_pasv_indc, plup_pasv_indc, futp_pasv_indc, perf_pasv_inf and futp_pasv_inf (with changes if deponent/semideponent etc)
-- acc_sup: determines futr_pasv_inf (and futr_actv_inf if there's no futr_pasv_ptc)
-- 10. Handle "revertor"-type: deponent in the present, but not in the perfect.
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local export = {}
local test_new_la_verb_module = false
local m_la_headword = require("Module:la-headword")
local m_la_nominal = require("Module:la-nominal")
local m_la_utilities = require("Module:la-utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local m_utilities = require("Module:utilities")
local lang = require("Module:languages").getByCode("la")
local sc = require("Module:scripts").getByCode("Latn")
local allowed_subtypes = mw.loadData("Module:la-verb/data").allowed_subtypes
local PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Reconstruction" then
PAGENAME = "*" .. PAGENAME
end
-- Conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local make_conjugation = {}
local add_form = m_la_utilities.add_form
local concat = table.concat
local do_generate_noun_forms = m_la_nominal.do_generate_noun_forms
local do_generate_adj_forms = m_la_nominal.do_generate_adj_forms
local dump = mw.dumpObject
local flatten = m_table.flatten
local form_contains = m_la_utilities.form_contains
local form_is_empty = m_la_utilities.form_is_empty
local forms_equal = m_la_utilities.forms_equal
local full_link = m_links.full_link
local insert = table.insert
local insert_if_not = m_table.insertIfNot
local ipairs = ipairs
local pairs = pairs
local pattern_escape = require("Module:string utilities").pattern_escape
local remove = table.remove
local remove_forms = m_la_utilities.remove_forms
local remove_links = m_links.remove_links
local split = mw.text.split
local table_len = m_table.length
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local tostring = tostring
local type = type
local u = mw.ustring.char
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = mw.ustring.sub
local MACRON = u(0x304)
local BREVE = u(0x306)
local TREMA = u(0x308)
local LENGTH = MACRON .. "?" .. BREVE .. "?" .. TREMA .. "?"
local vowel = "[aeiouyAEIOUY]"
local generic_slots = {}
local non_generic_slots = {}
local potential_lemma_slots = {
"1s_pres_actv_indc", -- regular
"3s_pres_actv_indc", -- impersonal
"1s_perf_actv_indc", -- "coepī"
"3s_perf_actv_indc", -- doesn't occur?
"2s_pres_actv_impr", -- "cedo"
}
local persons = {"1s", "2s", "3s", "1p", "2p", "3p"}
local persons_2 = {"2s", "2p"}
local persons_23 = {"2s", "3s", "2p", "3p"}
local function handle_person(t, v, mood)
local non_pers_slot = t .. "_" .. v .. "_" .. mood
insert(generic_slots, non_pers_slot)
for _, p in ipairs(persons) do
insert(non_generic_slots, p .. "_" .. non_pers_slot)
end
end
local voices = {"actv", "pasv"}
local indc_tenses = {"pres", "impf", "futr", "perf", "plup", "futp", "sigf"}
local subj_tenses = {"pres", "impf", "perf", "plup", "siga"}
local impr_tenses = {"pres", "futr"}
local nonfin_tenses = {"pres", "futr", "perf", "futp", "perp"}
for _, v in ipairs(voices) do
for _, t in ipairs(indc_tenses) do
handle_person(t, v, "indc")
end
for _, t in ipairs(subj_tenses) do
handle_person(t, v, "subj")
end
for _, t in ipairs(impr_tenses) do
handle_person(t, v, "impr")
end
for _, f in ipairs{"inf", "ptc"} do
for _, t in ipairs(nonfin_tenses) do
insert(non_generic_slots, t .. "_" .. v .. "_" .. f)
end
end
end
insert(non_generic_slots, "sigm_actv_inf")
local ger_cases = {"gen", "dat", "acc", "abl"}
for _, c in ipairs(ger_cases) do
insert(non_generic_slots, c .. "_ger")
end
local sup_cases = {"acc", "abl"}
for _, c in ipairs(sup_cases) do
insert(non_generic_slots, c .. "_sup")
end
local function track(page)
require("Module:debug").track("la-verb/" .. page)
end
-- Constant version of :find()
local function cfind(str, text)
return str:find(text, nil, true)
end
-- Used for testing differences between production and sandbox module; see `test_new_la_verb_module` arm in show().
-- Do not delete!
local function concat_vals(val)
if type(val) == "table" then
return table.concat(val, ",")
else
return val
end
end
local function make_link(page, display, face, accel)
return full_link({term = page, alt = display, lang = lang, sc = sc, accel = accel}, face)
end
-- Iterate over all the "slots" associated with a verb declension, where a slot
-- is e.g. 1s_pres_actv_indc (a non-generic slot), pres_actv_indc (a generic slot),
-- or linked_1s_pres_actv_indc (a linked slot). Only include the generic and/or linked
-- slots if called for.
local function iter_slots(include_generic, include_linked)
-- stage == 1: non-generic slots
-- stage == 2: generic slots
-- stage == 3: linked slots
local stage = 1
local slotnum = 0
local max_slotnum = table_len(non_generic_slots)
return function()
slotnum = slotnum + 1
if slotnum > max_slotnum then
slotnum = 1
stage = stage + 1
if stage == 2 then
if include_generic then
max_slotnum = table_len(generic_slots)
else
stage = stage + 1
end
end
if stage == 3 then
if include_linked then
max_slotnum = table_len(potential_lemma_slots)
else
stage = stage + 1
end
end
if stage > 3 then
return nil
end
end
if stage == 1 then
return non_generic_slots[slotnum]
elseif stage == 2 then
return generic_slots[slotnum]
end
return "linked_" .. potential_lemma_slots[slotnum]
end
end
local function ine(val)
if val == "" then
return nil
end
return val
end
-- Construct a simple one- or two-part link, which will be put through full_link later.
local function make_raw_link(page, display)
if page and display then
return "[[" .. page .. "|" .. display .. "]]"
elseif page then
return "[[" .. page .. "]]"
end
return display
end
local function split_prefix_and_base(lemma, main_verbs)
lemma = toNFD(lemma)
for _, main in ipairs(main_verbs) do
local orig_main = main
main = toNFD(main)
local main_pattern = pattern_escape(main)
local prefix = umatch(lemma, "^(.*)" .. main_pattern .. "$")
-- If `main` starts with a vowel and there's no macron or trema, try it with a trema iff it's preceded by a vowel.
if (
not prefix and
main:match("^" .. vowel) and
not umatch(main, "^.[" .. MACRON .. TREMA .. "]")
) then
main_pattern = pattern_escape((main:gsub("^.", "%0" .. TREMA)))
prefix = umatch(lemma, "^(.*" .. vowel .. LENGTH .. ")" .. main_pattern .. "$")
end
if prefix then
return toNFC(prefix), orig_main
end
end
require("Module:collation").sort(main_verbs, lang)
error(("Conjugation %s may only be used with %s, or a derived verb that ends with one of them"):format(
dump("irreg"), m_table.serialCommaJoin(main_verbs, {conj = "or", dontTag = true, dump = true})
))
end
-- Given an ending (or possibly a full regex matching the entire lemma, if
-- a regex group is present), return the base minus the ending, or nil if
-- the ending doesn't match.
local function extract_base(lemma, ending)
if cfind(ending, "(") then
return umatch(lemma, ending)
end
return umatch(lemma, "^(.*)" .. ending .. "$")
end
local function check_spec(lemma, spec, specified_subtypes)
local ending, subtypes, incompatible = unpack(spec)
if incompatible then
for _, subtype in ipairs(incompatible) do
if specified_subtypes[subtype] then
return
end
end
end
for _, subtype in ipairs(subtypes) do
-- A cancelled subtype will have the value false.
if specified_subtypes[subtype] == false then
return
end
end
local base = extract_base(lemma, ending)
if base then
return base, subtypes
end
end
-- Given ENDINGS_AND_SUBTYPES (a list of pairs of endings with associated
-- subtypes, where each pair consists of a single ending spec and a list of
-- subtypes), check each ending in turn against LEMMA. If it matches, return
-- the pair BASE, SUBTYPES where BASE is the remainder of LEMMA minus the
-- ending, and SUBTYPES is the subtypes associated with the ending. If no
-- endings match, throw an error if DECLTYPE is non-nil, mentioning the
-- DECLTYPE (the user-specified declension); but if DECLTYPE is nil, just
-- return the pair nil, nil.
--
-- The ending spec in ENDINGS_AND_SUBTYPES is one of the following:
--
-- 1. A simple string, e.g. "ātur", specifying an ending.
-- 2. A regex that should match the entire lemma (it should be anchored at
-- the beginning with ^ and at the end with $), and contains a single
-- capturing group to match the base.
local function get_subtype_by_ending(lemma, conj, specified_subtypes, specs)
for _, spec in ipairs(specs) do
local base, subtypes = check_spec(lemma, spec, specified_subtypes)
if base then
return base, subtypes
end
end
if conj then
error("Unrecognized ending for conjugation " .. conj .. " verb: " .. lemma)
end
return nil, nil
end
local genders = {"m", "f", "n", "mp", "fp", "np"}
local irreg_verbs = {
"aiō",
"aiiō",
"aijō",
"ajō",
"cedo", -- final "o" not "ō"
"dīcō",
"dūcō",
"edō", -- FIXME: Will praedō cause problems?
"ëdō",
"dō", -- list after edō
"eō",
"ëō",
"faciō",
"ferō",
"fīō",
"inquam",
"mālō",
"nōlō",
"possum",
"sum",
"volō",
}
local irreg_verbs_conj = {
["aiō"] = "3rd-io",
["aiiō"] = "3rd-io",
["aijō"] = "3rd-io",
["ajō"] = "3rd-io",
["cedo"] = "irreg",
["dīcō"] = "3rd",
["dō"] = "1st",
["dūcō"] = "3rd",
["edō"] = "3rd",
["ëdō"] = "3rd",
["eō"] = "irreg",
["ëō"] = "irreg",
["faciō"] = "3rd-io",
["ferō"] = "3rd",
["fīō"] = "3rd",
["inquam"] = "irreg",
["mālō"] = "irreg",
["nōlō"] = "irreg",
["possum"] = "irreg",
["sum"] = "irreg",
["volō"] = "irreg",
}
local function detect_decl_and_subtypes(args)
local subtypes, specs = {}, split(args[1] or "", "%.")
local conj_arg = remove(specs, 1)
for _, spec in ipairs(specs) do
subtypes[spec:gsub("%-", "")] = spec:sub(1, 1) ~= "-"
end
local orig_lemma = toNFC(args[2] or PAGENAME)
local lemma = remove_links(orig_lemma)
local base, conj, irreg, detected_subtypes
local base_conj_arg, auto_perf_supine = conj_arg:match("^([1-4/]+)(%+%+?)$")
if base_conj_arg then
if (
(auto_perf_supine == "++" and not (base_conj_arg == "4")) or
(auto_perf_supine == "+" and not (base_conj_arg == "1" or base_conj_arg == "2" or base_conj_arg == "4"))
) then
error("Conjugation type " .. base_conj_arg .. auto_perf_supine .. " not allowed")
end
conj_arg = base_conj_arg
end
if orig_lemma:sub(1, 1) == "-" then
subtypes.suffix = true
end
local auto_perf, auto_supine, auto_sigm
if subtypes.sigmpasv then
subtypes.sigm = true
end
if subtypes.sigm then
auto_sigm = true
end
if conj_arg == "1" then
conj = "1st"
base, detected_subtypes = get_subtype_by_ending(lemma, "1", subtypes, {
{"ō", {}},
{"or", {"depon"}},
{"at", {"impers"}},
{"ātur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"ā", {"imponly"}},
{"āre", {"depon", "imponly"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
else
auto_perf = base .. "āv"
auto_supine = base .. "āt"
end
end
if auto_sigm then
auto_sigm = base .. "āss"
end
if subtypes.suffix then
subtypes.p3inf = true
end
elseif conj_arg == "2" then
conj = "2nd"
base, detected_subtypes = get_subtype_by_ending(lemma, "2", subtypes, {
{"eō", {}},
{"eor", {"depon"}},
{"et", {"impers"}},
{"ētur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"ē", {"imponly"}},
{"ēre", {"depon", "imponly"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
else
auto_perf = base .. "u"
auto_supine = base .. "it"
end
end
if auto_sigm then
auto_sigm = base .. "ēss"
end
elseif conj_arg == "3" or conj_arg == "3/4" then
base, detected_subtypes = get_subtype_by_ending(lemma, conj_arg == "3/4" and "3/4" or nil, subtypes, {
{"iō", {"i"}},
{"ior", {"depon", "i"}},
})
if base then
conj = conj_arg == "3/4" and "3rd/4th" or "3rd-io"
else
base, detected_subtypes = get_subtype_by_ending(lemma, "3", subtypes, {
{"ō", {}},
{"or", {"depon"}},
{"it", {"impers"}, {"nopres"}},
{"itur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"e", {"imponly"}, {"depon"}},
{"ere", {"depon", "imponly"}},
})
if subtypes.i then
conj = "3rd-io"
else
conj = "3rd"
end
end
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
end
if subtypes.suffix then
auto_perf = "-"
auto_supine = "-"
auto_sigm = "-"
end
elseif conj_arg == "4" then
conj = "4th"
base, detected_subtypes = get_subtype_by_ending(lemma, "4", subtypes, {
{"iō", {}},
{"ior", {"depon"}},
{"it", {"impers"}, {"nopres"}},
{"ītur", {"depon", "impers"}},
{"ī", {"nopres"}, {"imponly"}},
{"it", {"nopres", "impers"}},
{"ī", {"imponly"}},
{"īre", {"depon", "imponly"}},
})
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
elseif auto_perf_supine == "++" then
auto_perf = base .. "īv/" .. base .. "i"
auto_supine = base .. "īt"
elseif auto_perf_supine == "+" then
auto_perf = base .. "īv"
auto_supine = base .. "īt"
end
if auto_sigm then
auto_sigm = base .. "īss"
end
elseif conj_arg == "irreg" then
irreg = true
local prefix
prefix, base = split_prefix_and_base(lemma, irreg_verbs)
conj = irreg_verbs_conj[base]
args[1] = base
args[2] = prefix
-- args[3] and args[4] are used by ferō and sum and stay where they are
detected_subtypes = {}
else
error("Unrecognized conjugation: " .. dump(conj_arg))
end
for _, detected_subtype in ipairs(detected_subtypes) do
if detected_subtype == "impers" and subtypes["3only"] then
-- 3only overrides impers
elseif detected_subtype == "nopres" and subtypes.perfaspres then
-- perfaspres overrides nopres
else
subtypes[detected_subtype] = true
end
end
-- Get the gender of the verb's complement.
local gender
for _, g in ipairs(genders) do
if subtypes[g] then
if gender then
error(("Only one of the subtypes %s may be specified"):format(
m_table.serialCommaJoin(genders, {conj = "or", dontTag = true, dump = true})
))
end
gender = g
end
end
if not gender then
gender = (subtypes.impers or subtypes.passimpers or subtypes["3only"] or subtypes["pass3only"]) and "n" or "m"
end
if subtypes.nopres or subtypes.perfaspres then
subtypes.noger = true
end
if not irreg then
args[1] = base
local perf_stem, supine_stem
if subtypes.depon or subtypes.semidepon or subtypes.nopres or subtypes.perfaspres then
supine_stem = args[3] or auto_supine
if supine_stem == "-" and not subtypes.suffix then
supine_stem = nil
end
if not supine_stem then
if subtypes.depon or subtypes.semidepon then
subtypes.noperf = true
end
subtypes.nosup = true
end
if subtypes.sigm then
local sigm_stem = args[5] or auto_sigm
if sigm_stem == "-" and not subtypes.suffix then
sigm_stem = nil
end
args[5] = sigm_stem
end
args[2] = supine_stem
args[3] = nil
else
perf_stem = args[3] or auto_perf
if perf_stem == "-" and not subtypes.suffix then
perf_stem = nil
end
if not perf_stem then
subtypes.noperf = true
end
supine_stem = args[4] or auto_supine
if supine_stem == "-" and not subtypes.suffix then
supine_stem = nil
end
if not supine_stem then
subtypes.nosup = true
end
if subtypes.sigm then
local sigm_stem = args[5] or auto_sigm
if sigm_stem == "-" and not subtypes.suffix then
sigm_stem = nil
end
args[5] = sigm_stem
end
args[2] = perf_stem
args[3] = supine_stem
end
args[4] = nil
end
if auto_sigm and subtypes.depon then
subtypes.sigmpasv = true
end
for subtype in pairs(subtypes) do
if (
subtype == "i" and not (conj_arg == "3" or conj_arg == "3/4") or
not allowed_subtypes[subtype]
) then
error(("Unrecognized verb subtype %s for this conjugation"):format(dump(subtype)))
end
end
return conj, irreg, subtypes, orig_lemma, lemma, gender
end
local function _add_forms(forms, keytype, persons, stem, ...)
for i, p in ipairs(persons) do
local suf = select(i, ...)
if suf ~= nil then
add_form(forms, p .. "_" .. keytype, stem, suf)
end
end
end
-- Add a value to all persons/numbers of a given tense/voice/mood, e.g.
-- "pres_actv_indc" (specified by KEYTYPE). If a value is already present
-- in a key, it won't be added again.
--
-- The value for a given person/number combination is formed by concatenating
-- STEM and the appropriate suffix for that person/number, e.g. SUF1S. The
-- suffix can be a list, in which case STEM will be concatenated in turn to
-- each value in the list and all the resulting forms added to the key. To
-- not add a value for a specific person/number, specify nil or {} for the
-- suffix for the person/number.
local function add_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons, stem, ...)
end
-- Add a value to the 2nd person (singular and plural) of a given
-- tense/voice/mood. This works like add_forms().
local function add_2_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons_2, stem, ...)
end
-- Add a value to the 2nd and 3rd persons (singular and plural) of a given
-- tense/voice/mood. This works like add_forms().
local function add_23_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons_23, stem, ...)
end
local function override(args, data)
local forms = data.forms
for slot in iter_slots(true, false) do
if args[slot] then
forms[slot] = split(args[slot], "/")
end
end
end
local function set_linked_forms(data, typeinfo)
-- Generate linked variants of slots that may be the lemma.
-- If the form is the same as the lemma (with links removed),
-- substitute the original lemma (with links included).
local forms = data.forms
for _, slot in ipairs(potential_lemma_slots) do
local formval = forms[slot]
local linked_forms = {}
if formval then
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form == typeinfo.lemma then
insert(linked_forms, typeinfo.orig_lemma)
else
insert(linked_forms, form)
end
end
end
forms["linked_" .. slot] = linked_forms
end
end
local function link_words_if_unlinked(affix)
return affix:match("%[%[.-]]") and affix or ugsub(affix, "%w+", "[[%0]]")
end
local function get_affix(data, key)
local affix = data[key] or ""
return link_words_if_unlinked(affix), remove_links(affix)
end
-- Add prefixes and suffixes to non-generic slots. The generic slots (e.g.
-- perf_pasv_indc, whose text indicates to use the past passive participle +
-- the present active indicative of [[sum]]), handle prefixes and suffixes
-- themselves in make_perfect_passive().
local function add_prefix_suffix(data)
if not data.prefix and not data.suffix then
return
end
local active_prefix, active_prefix_no_links = get_affix(data, "prefix")
local passive_prefix, passive_prefix_no_links = get_affix(data, "passive_prefix")
local plural_prefix, plural_prefix_no_links = get_affix(data, "plural_prefix")
local plural_passive_prefix, plural_passive_prefix_no_links = get_affix(data, "plural_passive_prefix")
local active_suffix, active_suffix_no_links = get_affix(data, "suffix")
local passive_suffix, passive_suffix_no_links = get_affix(data, "passive_suffix")
local plural_suffix, plural_suffix_no_links = get_affix(data, "plural_suffix")
local plural_passive_suffix, plural_passive_suffix_no_links = get_affix(data, "plural_passive_suffix")
local forms = data.forms
for slot in iter_slots(false, true) do
local prefix, suffix, prefix_no_links, suffix_no_links
if cfind(slot, "pasv") and slot:match("[123]p") then
prefix = plural_passive_prefix
suffix = plural_passive_suffix
prefix_no_links = plural_passive_prefix_no_links
suffix_no_links = plural_passive_suffix_no_links
elseif cfind(slot, "pasv") and not cfind(slot, "_inf") then
prefix = passive_prefix
suffix = passive_suffix
prefix_no_links = passive_prefix_no_links
suffix_no_links = passive_suffix_no_links
elseif slot:match("[123]p") then
prefix = plural_prefix
suffix = plural_suffix
prefix_no_links = plural_prefix_no_links
suffix_no_links = plural_suffix_no_links
else
prefix = active_prefix
suffix = active_suffix
prefix_no_links = active_prefix_no_links
suffix_no_links = active_suffix_no_links
end
local formval = forms[slot]
if not form_is_empty(formval) then
local affixed_forms = {}
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form_is_empty(form) then
insert(affixed_forms, form)
elseif slot:match("^linked") then
-- If we're dealing with a linked slot, include the original
-- links in the prefix/suffix and also add a link around the
-- form itself if links aren't already present. (Note, above
-- we early-exited if there was no prefix and no suffix.)
if not form:match("%[%[.-]]") then
form = "[[" .. form .. "]]"
end
insert(affixed_forms, prefix .. form .. suffix)
elseif form:match("%[%[.-]]") then
-- If not dealing with a linked slot, but there are links
-- in the slot, include the original, potentially linked
-- versions of the prefix and suffix (e.g. in perfect
-- passive forms).
insert(affixed_forms, prefix .. form .. suffix)
else
-- Otherwise, use the non-linking versions of the prefix and
-- suffix so that the whole term (including prefix/suffix)
-- gets linked.
insert(affixed_forms, prefix_no_links .. form .. suffix_no_links)
end
end
forms[slot] = affixed_forms
end
end
end
local function notes_override(args, data)
local notes = {args["note1"], args["note2"], args["note3"]}
for n, note in pairs(notes) do
if note == "-" then
data.footnotes[n] = nil
elseif note == "p3inf" then
data.footnotes[n] = "The present passive infinitive in ''-ier'' is a rare poetic form which is attested."
elseif note == "poetsyncperf" then
data.footnotes[n] = "At least one rare poetic syncopated perfect form is attested."
elseif note == "sigm" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\")."
elseif note == "sigmpasv" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\"). It is also attested as having a rare sigmatic future passive indicative form (\"will have been\"), which is not attested in the plural for any verb."
elseif note == "sigmdepon" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense (which is not attested in the plural for any verb)."
elseif note then
data.footnotes[n] = note
end
end
if args["notes"] == "-" then
data.footnotes = {}
end
end
-- Space added by default; hyphens unchanged; underscore represents no space.
local affix_joining_chars = {
[""] = " ",
["-"] = "-",
["_"] = "",
}
local function normalize_prefix(prefix)
return prefix and prefix:gsub("[%-_]?$", affix_joining_chars, 1)
end
local function normalize_suffix(suffix)
return suffix and suffix:gsub("^[%-_]?", affix_joining_chars, 1)
end
local function handle_subtype_affix(args, affix, subtype_affix, normalize_func)
if args[subtype_affix] then
if not args[affix] then
error(("Can't specify %s= without %s="):format(subtype_affix, affix))
end
return normalize_func(args[subtype_affix])
end
end
local function handle_affix(args, data, affix, normalize_func)
data[affix] = normalize_func(args[affix])
for _, subtype in ipairs{"passive", "plural"} do
local subtype_affix = subtype .. "_" .. affix
data[subtype_affix] = handle_subtype_affix(args, affix, subtype_affix, normalize_func) or data[affix]
end
-- First fall back to the passive (e.g. "poenās dare", where the plural noun
-- is used with both singular and plural verbs, but there's a separate
-- passive form ''poenae datur''), then to the plural prefix, then to the
-- base prefix.
local subtype_affix = "plural_passive_" .. affix
data[subtype_affix] = handle_subtype_affix(args, affix, subtype_affix, normalize_func) or
data["passive_" .. affix] or data["plural_" .. affix] or data[affix]
end
function export.make_data(parent_args, from_headword, def1, def2)
local params = {
[1] = {required = true, default = def1 or "1+"},
[2] = {required = true, default = def2 or "amō"},
[3] = true,
[4] = true,
[5] = true,
prefix = true,
passive_prefix = true,
plural_prefix = true,
plural_passive_prefix = true,
suffix = true,
passive_suffix = true,
plural_suffix = true,
plural_passive_suffix = true,
label = true,
note1= true,
note2= true,
note3= true,
notes= true,
-- examined directly in export.show()
search = true,
json = {type = "boolean"},
}
for slot in iter_slots(true, false) do
params[slot] = true
end
if from_headword then
local list = {list = true}
params.lemma = list
params.id = true
params.cat = list
end
local args = require("Module:parameters").process(parent_args, params)
local conj, irreg, subtypes, orig_lemma, lemma, gender = detect_decl_and_subtypes(args)
-- note: the addition of red superscripted footnotes ('<sup class="roa-red-superscript">' ... </sup>) is only implemented for the three form printing loops in which it is used
local data = {
forms = {},
title = {},
categories = args.cat and m_table.deepCopy(args.cat) or {},
form_footnote_indices = {},
footnotes = {},
id = args.id,
overriding_lemma = args.lemma,
gender = gender,
}
local typeinfo = {
lemma = lemma,
orig_lemma = orig_lemma,
conj = conj,
irreg = irreg,
subtypes = subtypes,
}
handle_affix(args, data, "prefix", normalize_prefix)
handle_affix(args, data, "suffix", normalize_suffix)
-- Generate the verb forms
make_conjugation(args, data, typeinfo)
-- Generate the title text
m_la_headword.verb_title(data.title, typeinfo, export.get_lemma_forms(data))
-- Override with user-set forms
override(args, data)
-- Set linked_* forms
set_linked_forms(data, typeinfo)
-- Prepend any prefixes, append any suffixes
add_prefix_suffix(data)
if args["label"] then
insert_if_not(data.title, args["label"])
end
notes_override(args, data)
-- If json=1 specified, return a JSON string; used by bots
if args.json then
return require("Module:JSON").toJSON {
data = data,
typeinfo = typeinfo
}
end
return data, typeinfo
end
local ptc_lemma_form = {
["m"] = "sg_m",
["f"] = "sg_f",
["n"] = "sg_n",
["mp"] = "pl_m",
["fp"] = "pl_f",
["np"] = "pl_n",
}
-- Make the gerund and gerundive/future passive participle. For the forms
-- labeled "gerund", we generate both gerund and gerundive variants if there's
-- a case-specific prefix or suffix for the case in question; otherwise we
-- generate only the gerund per se. BASE is the stem (ending in -nd).
-- UND_VARIANT, if true, means that a gerundive in -und should be generated
-- along with a gerundive in -end.
local function make_gerund(data, typeinfo, base, und_variant)
local subtypes = typeinfo.subtypes
if subtypes.noger then
return
end
local forms, gender = data.forms, data.gender
local slot = "nom_" .. ptc_lemma_form[gender]
add_form(forms, "futr_pasv_ptc", "", do_generate_adj_forms({base .. "us<1&2+>"}, "participles", "bare").forms[slot])
if und_variant and not (subtypes.nound or base:match("[vV]end$") or umatch(base, "[uU]" .. LENGTH .. "end$")) then
-- Per Lane's grammar section 899: "Verbs in -ere and -īre often have
-- -undus, when not preceded by u or v, especially in formal style"
-- There is also an optional exclusion if -undus is not attested
add_form(forms, "futr_pasv_ptc", "", do_generate_adj_forms({base:gsub("end$", "und") .. "us<1&2+>"}, "participles", "bare").forms[slot])
end
local ger_forms = do_generate_noun_forms({base .. "um<2>"}, "nouns", "bare").forms
for _, case in ipairs(ger_cases) do
for _, form in ipairs(ger_forms[case .. "_sg"]) do
add_form(forms, case .. "_ger", "", form)
end
end
end
-- Conjugation functions
local function get_regular_stems(args, typeinfo)
local subtypes = typeinfo.subtypes
-- Get the parameters
if subtypes.nopres or subtypes.perfaspres then
typeinfo.pres_stem = nil
typeinfo.perf_stem = ine(args[1])
typeinfo.supine_stem = ine(args[2])
elseif subtypes.depon or subtypes.semidepon then
-- Deponent and semi-deponent verbs don't have the perfective principal part.
-- But optionally semi-deponent verbs do.
typeinfo.pres_stem = ine(args[1])
typeinfo.perf_stem = nil
typeinfo.supine_stem = ine(args[2])
else
typeinfo.pres_stem = ine(args[1])
typeinfo.perf_stem = ine(args[2])
typeinfo.supine_stem = ine(args[3])
end
if subtypes.sigm then
typeinfo.sigm_stem = ine(args[5])
end
-- Prepare stems
if not (typeinfo.pres_stem or subtypes.nopres or subtypes.perfaspres) then -- Template:
error("Present stem has not been provided")
end
if typeinfo.perf_stem then
typeinfo.perf_stem = split(typeinfo.perf_stem, "/")
else
typeinfo.perf_stem = {}
end
if typeinfo.supine_stem then
typeinfo.supine_stem = split(typeinfo.supine_stem, "/")
else
typeinfo.supine_stem = {}
end
if typeinfo.sigm_stem then
typeinfo.sigm_stem = split(typeinfo.sigm_stem, "/")
else
typeinfo.sigm_stem = {}
end
end
local function set_conj_categories(ord, data, typeinfo)
local categories, subtypes = data.categories, typeinfo.subtypes
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs")
if subtypes.depon then
insert_if_not(categories, "Latin " .. ord .. " conjugation deponent verbs")
end
if subtypes.noperf then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing perfect stem")
end
if subtypes.nosup then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem")
elseif subtypes.supfutractvonly then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem except in the future active participle")
end
local pres_stem = typeinfo.pres_stem
if not pres_stem then
return
end
pres_stem = pres_stem and pres_stem:gsub("[Qq]u", "\1")
for _, perf_stem in ipairs(typeinfo.perf_stem) do
perf_stem = perf_stem:gsub("[Qq]u", "\1")
if perf_stem == pres_stem .. "āv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -āv-")
elseif perf_stem == pres_stem .. "ēv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -ēv-")
elseif perf_stem == pres_stem .. "īv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -īv-")
elseif perf_stem == pres_stem .. "i" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -i-")
elseif perf_stem == pres_stem .. "u" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -u-")
elseif perf_stem == pres_stem then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with suffixless perfect")
elseif perf_stem:match("[sx]$") then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -s- or -x-")
else
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with irregular perfect")
end
end
end
-- Form-generating functions
local make_pres = {}
make_pres["1st"] = function(data, typeinfo, pres_stem)
local forms = data.forms
local a = typeinfo.subtypes.shorta and "a" or "ā"
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "ās", "at", a .. "mus", a .. "tis", "ant")
add_forms(forms, "impf_actv_indc", pres_stem, a .. "bam", a .. "bās", a .. "bat", a .. "bāmus", a .. "bātis", a .. "bant")
add_forms(forms, "futr_actv_indc", pres_stem, a .. "bō", a .. "bis", a .. "bit", a .. "bimus", a .. "bitis", a .. "bunt")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {a .. "ris", a .. "re"}, a .. "tur", a .. "mur", a .. "minī", "antur")
add_forms(forms, "impf_pasv_indc", pres_stem, a .. "bar", {a .. "bāris", a .. "bāre"}, a .. "bātur", a .. "bāmur", a .. "bāminī", a .. "bantur")
add_forms(forms, "futr_pasv_indc", pres_stem, a .. "bor", {a .. "beris", a .. "bere"}, a .. "bitur", a .. "bimur", a .. "biminī", a .. "buntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "em", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_subj", pres_stem, a .. "rem", a .. "rēs", a .. "ret", a .. "rēmus", a .. "rētis", a .. "rent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "er", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_subj", pres_stem, a .. "rer", {a .. "rēris", a .. "rēre"}, a .. "rētur", a .. "rēmur", a .. "rēminī", a .. "rentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ā", a .. "te")
add_23_forms(forms, "futr_actv_impr", pres_stem, a .. "tō", a .. "tō", a .. "tōte", "antō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, a .. "re", a .. "minī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, a .. "tor", a .. "tor", nil, "antor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, a .. "re")
add_form(forms, "pres_pasv_inf", pres_stem, a .. "rī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "āns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "and")
end
make_pres["2nd"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "eō", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "ēbō", "ēbis", "ēbit", "ēbimus", "ēbitis", "ēbunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", pres_stem, "ērem", "ērēs", "ēret", "ērēmus", "ērētis", "ērent")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ē", "ēte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ētō", "ētō", "ētōte", "entō")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "eor", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ēbor", {"ēberis", "ēbere"}, "ēbitur", "ēbimur", "ēbiminī", "ēbuntur")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "ērer", {"ērēris", "ērēre"}, "ērētur", "ērēmur", "ērēminī", "ērentur")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ēre", "ēminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ētor", "ētor", nil, "entor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ēre")
add_form(forms, "pres_pasv_inf", pres_stem, "ērī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "ēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "end")
end
local function handle_old_impf(data, forms, pres_stem, ei, noteindex)
add_forms(forms, "impf_actv_indc", pres_stem .. ei, "bam", "bās", "bat", "bāmus", "bātis", "bant")
add_forms(forms, "impf_pasv_indc", pres_stem .. ei, "bar", {"bāris", "bāre"}, "bātur", "bāmur", "bāminī", "bantur")
for slot in pairs(data.forms) do
if cfind(slot, "impf") then
data.form_footnote_indices[slot] = noteindex
end
end
data.footnotes[noteindex] = "Pre-Classical."
end
local function handle_old_futr(data, forms, pres_stem, ei, noteindex)
add_forms(forms, "futr_actv_indc", pres_stem .. ei, "bō", "bis", "bit", "bimus", "bitis", "bunt")
add_forms(forms, "futr_pasv_indc", pres_stem .. ei, "bor", {"beris", "bere"}, "bitur", "bimur", "biminī", "buntur")
for slot in pairs(data.forms) do
if cfind(slot, "futr") then
data.form_footnote_indices[slot] = noteindex
end
end
data.footnotes[noteindex] = "Pre-Classical."
end
make_pres["3rd"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "is", "it", "imus", "itis", "unt")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {"eris", "ere"}, "itur", "imur", "iminī", "untur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ar", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
if typeinfo.subtypes.oldimpffutr then
handle_old_futr(data, forms, pres_stem, "ē", table_len(data.footnotes) + 1)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ar", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "untō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "untor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ere")
add_form(forms, "pres_pasv_inf", pres_stem, "ī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "ēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "end", "und-variant")
end
make_pres["3rd-io"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "is", "it", "imus", "itis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"eris", "ere"}, "itur", "imur", "iminī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "iuntō")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ere")
add_form(forms, "pres_pasv_inf", pres_stem, "ī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
make_pres["3rd/4th"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "ī̆s", "it", "ī̆mus", "ī̆tis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"eris", "īris", "ere", "īre"}, "ī̆tur", "ī̆mur", "ī̆minī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, {"erem", "īrem"}, {"erēs", "īrēs"}, {"eret", "īret"}, {"erēmus", "īrēmus"}, {"erētis", "īrētis"}, {"erent", "īrent"})
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, {"erer", "īrer"}, {"erēris", "īrēris", "erēre", "īrēre"}, {"erētur", "īrētur"}, {"erēmur", "īrēmur"}, {"erēminī", "īrēminī"}, {"erentur", "īrentur"})
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, {"e", "ī"}, "ī̆te")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ī̆tō", "ī̆tō", "ī̆tōte", "iuntō")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, {"ere", "īre"}, "ī̆minī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ī̆tor", "ī̆tor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, {"ere", "īre"})
add_form(forms, "pres_pasv_inf", pres_stem, {"ī", "īrī"})
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
make_pres["4th"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "īs", "it", "īmus", "ītis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"īris", "īre"}, "ītur", "īmur", "īminī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ītō", "ītō", "ītōte", "iuntō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ītor", "ītor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "īre")
add_form(forms, "pres_pasv_inf", pres_stem, "īrī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
local make_pres_mt = {}
function make_pres_mt:__call(data, typeinfo, pres_stem)
if not pres_stem then
return
end
return self[typeinfo.conj](data, typeinfo, pres_stem)
end
setmetatable(make_pres, make_pres_mt)
local function make_perf(data, perf_stem, no_inf)
if not perf_stem then
return
end
local forms = data.forms
if type(perf_stem) ~= "table" then
perf_stem = {perf_stem}
end
for _, stem in ipairs(perf_stem) do
-- Perfective indicative
add_forms(forms, "perf_actv_indc", stem, "ī", "istī", "it", "imus", "istis", {"ērunt", "ēre"})
add_forms(forms, "plup_actv_indc", stem, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futp_actv_indc", stem, "erō", "eris", "erit", "erimus", "eritis", "erint")
-- Perfective subjunctive
add_forms(forms, "perf_actv_subj", stem, "erim", "erīs", "erit", "erīmus", "erītis", "erint")
add_forms(forms, "plup_actv_subj", stem, "issem", "issēs", "isset", "issēmus", "issētis", "issent")
-- Perfect infinitive
if not no_inf then
add_form(forms, "perf_actv_inf", stem, "isse")
end
end
end
local function make_true_supine(data, typeinfo, supine_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.supfutractvonly or not supine_stem then
return
end
local forms = data.forms
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
for _, stem in ipairs(supine_stem) do
local supine_forms = do_generate_noun_forms({stem .. "us<4>"}, "nouns", "bare").forms
add_form(forms, "acc_sup", "", supine_forms["acc_sg"])
add_form(forms, "abl_sup", "", supine_forms["abl_sg"])
add_form(forms, "futr_pasv_inf", forms["acc_sup"], " īrī")
if subtypes.nofutractvptc then
add_form(forms, "futr_actv_inf", forms["acc_sup"], " īre")
end
end
end
local function make_perf_pasv_ptc(data, typeinfo, supine_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.supfutractvonly or not supine_stem then
return
end
local forms, gender = data.forms
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
gender = "m" -- perf_pasv_ptc becomes perf_actv_ptc, so the gender of the complement isn't relevant
else
gender = data.gender
end
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
for _, stem in ipairs(supine_stem) do
-- Perfect passive participle
local perf_pasv_ptc_forms = do_generate_adj_forms({stem .. "us<1&2+>"}, "participles", "bare").forms
local form = perf_pasv_ptc_forms["nom_" .. ptc_lemma_form[gender]]
add_form(forms, "perf_pasv_ptc", "", form)
add_forms(forms, "perf_pasv_indc", form, " sum", " es", " est", nil, nil, nil)
add_forms(forms, "plup_pasv_indc", form, " eram", " erās", " erat", nil, nil, nil)
add_forms(forms, "futp_pasv_indc", form, " erō", " eris", " erit", nil, nil, nil)
add_forms(forms, "perf_pasv_subj", form, " sim", " sīs", " sit", nil, nil, nil)
add_forms(forms, "plup_pasv_subj", form, " essem", " essēs", " esset", nil, nil, nil)
form = perf_pasv_ptc_forms["nom_" .. ptc_lemma_form[gender]:gsub("sg", "pl")]
add_forms(forms, "perf_pasv_indc", form, nil, nil, nil, " sumus", " estis", " sunt")
add_forms(forms, "plup_pasv_indc", form, nil, nil, nil, " erāmus", " erātis", " erant")
add_forms(forms, "futp_pasv_indc", form, nil, nil, nil, " erimus", " eritis", " erint")
add_forms(forms, "perf_pasv_subj", form, nil, nil, nil, " sīmus", " sītis", " sint")
add_forms(forms, "plup_pasv_subj", form, nil, nil, nil, " essēmus", " essētis", " essent")
form = perf_pasv_ptc_forms["acc_" .. ptc_lemma_form[gender]]
add_form(forms, "perf_pasv_inf", form, " esse")
add_form(forms, "futp_pasv_inf", form, " fore")
end
end
-- A final "u" on the supine stem is omitted (e.g. "mortu" to "moritūrus").
local function make_futr_actv_ptc_stem(supine_stem)
local futr_actv_ptc_stem = {}
for _, stem in ipairs(supine_stem) do
insert(futr_actv_ptc_stem, (stem:gsub("u?$", "")))
end
return futr_actv_ptc_stem
end
local function make_futr_actv_ptc(data, typeinfo, futr_actv_ptc_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.nofutr or subtypes.nofutractvptc or not futr_actv_ptc_stem then
return
end
local forms = data.forms
if type(futr_actv_ptc_stem) ~= "table" then
futr_actv_ptc_stem = {futr_actv_ptc_stem}
end
for _, stem in ipairs(futr_actv_ptc_stem) do
local futr_actv_ptc_forms = do_generate_adj_forms({stem .. "ūrus<1&2+>"}, "participles", "bare").forms
add_form(forms, "futr_actv_ptc", "", futr_actv_ptc_forms["nom_sg_m"])
local form = futr_actv_ptc_forms["acc_sg_m"]
add_form(forms, "futr_actv_inf", form, " esse")
add_form(forms, "perp_actv_inf", form, " fuisse")
end
end
local function make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
if typeinfo.subtypes.nosup or not supine_stem then
return
end
make_true_supine(data, typeinfo, supine_stem)
make_perf_pasv_ptc(data, typeinfo, supine_stem)
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
if futr_actv_ptc_stem == nil then
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
end
make_futr_actv_ptc(data, typeinfo, futr_actv_ptc_stem)
end
local function make_sigm(data, typeinfo, sigm_stem)
local subtypes = typeinfo.subtypes
if not subtypes.sigm then
return
end
local forms = data.forms
if type(sigm_stem) ~= "table" then
sigm_stem = {sigm_stem}
end
local noteindex = table_len(data.footnotes) + 1
-- Deponent verbs use the passive form
for _, stem in ipairs(sigm_stem) do
-- Sigmatic future active indicative
add_forms(forms, "sigf_actv_indc", stem, "ō", "is", "it", "imus", "itis", "int")
-- Sigmatic future passive indicative
if subtypes.sigmpasv then
add_forms(forms, "sigf_pasv_indc", stem, "or", "eris", "itur", nil, nil, nil) -- Plurals not attested.
end
-- Sigmatic future active subjunctive
add_forms(forms, "siga_actv_subj", stem, "im", "īs", "īt", "īmus", "ītis", "int")
-- Perfect infinitive
if not no_inf then
add_form(forms, "sigm_actv_inf", stem, "ere")
end
end
data.form_footnote_indices["sigm"] = noteindex
if subtypes.depon then
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense (which is not attested in the plural for any verb).'
else
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\").'
if subtypes.sigmpasv then
data.footnotes[noteindex] = data.footnotes[noteindex] .. ' It is also attested as having a rare sigmatic future passive indicative form (\"will have been\"), which is not attested in the plural for any verb.'
end
end
end
make_conjugation["1st"] = function(args, data, typeinfo)
set_conj_categories("first", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
local forms = data.forms
if pres_stem == "dīlapid" then
add_form(forms, "3p_sigf_actv_indc", "", "dīlapidāssunt", 2)
elseif pres_stem == "invol" then
add_form(forms, "3s_sigf_actv_indc", "", "involāsit", 2)
elseif pres_stem == "viol" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_futp_actv_indc", "", "violārint", 2)
add_form(forms, "3p_perf_actv_subj", "", "violārint", 2)
add_form(forms, "3s_sigf_actv_indc", "", "violāsit", 2)
data.form_footnote_indices["3p_futp_actv_indc"] = tostring(noteindex)
data.form_footnote_indices["3p_perf_actv_subj"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
end
end
make_conjugation["2nd"] = function(args, data, typeinfo)
set_conj_categories("second", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if pres_stem == "noc" then
add_form(data.forms, "3s_siga_actv_subj", "", "noxsīt", 2)
end
end
make_conjugation["3rd"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if not pres_stem then
return
elseif toNFD(pres_stem):match(vowel .. MACRON .. "sc$") then
insert_if_not(data.categories, "Latin inchoative verbs")
end
if pres_stem:match("nōsc$") then
typeinfo.subtypes.poetsyncperf = true
elseif pres_stem == "ulcīsc" then
local forms = data.forms
local formval = forms["1s_sigf_actv_indc"]
if type(formval) ~= "table" then
formval = {formval}
end
forms["1s_sigf_actv_indc"] = formval
local noteindex = table_len(data.footnotes) + 1
for i, form in ipairs(formval) do
if form == "ulsō" then
add_form(forms, "1s_sigf_actv_indc", "ull", "ō", i + 1)
data.form_footnote_indices["1s_sigf_actv_indc"] = tostring(noteindex)
data.footnotes[noteindex] = 'The form \"ullō\" may have resulted from a later, erroneous misreading of \"ulsō\".'
break
end
end
end
end
make_conjugation["3rd-io"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
local supine_stem, futr_actv_ptc_stem = typeinfo.supine_stem
if supine_stem then
local subtypes = typeinfo.subtypes
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
for i, stem in ipairs(futr_actv_ptc_stem) do
-- TODO: generalise this as a subtype which is automatic for 3rd-io verbs with -rt in the supine
local unsync_stem = stem:gsub("rt$", "rit")
futr_actv_ptc_stem[i] = unsync_stem
if unsync_stem ~= stem then
subtypes.syncfutractvptc = true
end
end
typeinfo.futr_actv_ptc_stem = futr_actv_ptc_stem
end
make_pres(data, typeinfo, typeinfo.pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
end
make_conjugation["3rd/4th"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
set_conj_categories("fourth", data, typeinfo)
local supine_stem, futr_actv_ptc_stem = typeinfo.supine_stem
if supine_stem then
local subtypes = typeinfo.subtypes
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
for i, stem in ipairs(futr_actv_ptc_stem) do
-- TODO: generalise this as a subtype which is automatic for 3rd/4th verbs with -rt in the supine
local unsync_stem = stem:gsub("rt$", "rit")
futr_actv_ptc_stem[i] = unsync_stem
if unsync_stem ~= stem then
subtypes.syncfutractvptc = true
end
end
typeinfo.futr_actv_ptc_stem = futr_actv_ptc_stem
end
make_pres(data, typeinfo, typeinfo.pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
end
local function ivi_ive(form)
form = form:gsub("īvī", "iī")
form = form:gsub("īvi", "ī")
form = form:gsub("īve", "ī")
form = form:gsub("īvē", "ē")
return form
end
make_conjugation["4th"] = function(args, data, typeinfo)
set_conj_categories("fourth", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
local forms = data.forms
if form_contains(forms["1s_pres_actv_indc"], "serviō") or form_contains(forms["1s_pres_actv_indc"], "saeviō") then
add_forms(forms, "impf_actv_indc", pres_stem,
{"iēbam", "ībam"},
{"iēbās", "ībās"},
{"iēbat", "ībat"},
{"iēbāmus", "ībāmus"},
{"iēbātis", "ībātis"},
{"iēbant", "ībant"}
)
add_forms(forms, "futr_actv_indc", pres_stem,
{"iam", "ībō"},
{"iēs", "ībis"},
{"iet", "ībit"},
{"iēmus", "ībimus"},
{"iētis", "ībitis"},
{"ient", "ībunt"}
)
end
local subtypes = typeinfo.subtypes
if not (subtypes.alwayssyncperf or subtypes.optsyncperf) then
return
end
for key, formval in pairs(forms) do
if cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp") then
if type(formval) ~= "table" then
formval = {formval}
end
forms[key] = {}
for _, f in ipairs(formval) do
if subtypes.optsyncperf then
insert_if_not(forms[key], f)
end
insert_if_not(forms[key], ivi_ive(f))
end
end
end
end
-- Irregular conjugations.
local irreg_conjugations = {}
make_conjugation["irreg"] = function(args, data, typeinfo)
local verb = ine(args[1])
local prefix = ine(args[2])
if verb == nil then
error("The verb to be conjugated has not been specified.")
elseif not irreg_conjugations[verb] then
error(("Internal error: the irregular verb %s does not have a conjugation function specified."):format(dump(verb)))
end
typeinfo.prefix = prefix
-- Generate the verb forms
irreg_conjugations[verb](args, data, typeinfo)
end
for _, verb in ipairs{"aiō", "aiiō", "aijō", "ajō"} do
local stem = usub(verb, 1, -2)
local i_stem = stem:gsub("j$", "i")
irreg_conjugations[verb] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin active-only verbs")
insert_if_not(categories, "Latin defective verbs")
subtypes.highlydef = true
subtypes.nopass = true
subtypes.nosup = true
stem = (typeinfo.prefix or "") .. stem
-- TODO: add period and frequency notes.
add_forms(forms, "pres_actv_indc", stem, "ō", "s", "t", nil, "tis", "unt")
add_forms(forms, "impf_actv_indc", stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "perf_actv_indc", stem, nil, "stī", "t", nil, nil, {"ērunt", "ēre"})
add_forms(forms, "pres_actv_subj", stem, "am", "ās", "at", nil, nil, "ant")
add_form(forms, "3s_impf_actv_subj", stem, "eret")
add_form(forms, "2s_pres_actv_impr", stem, "")
add_form(forms, "pres_actv_inf", stem, "ere")
add_form(forms, "pres_actv_ptc", stem, "ēns")
end
end
irreg_conjugations["cedo"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin defective verbs")
subtypes.imponly = true
subtypes.nofutr = true
subtypes.nopass = true
subtypes.noperf = true
subtypes.nosup = true
local prefix = typeinfo.prefix or ""
forms["2s_pres_actv_impr"] = prefix .. "cedo"
forms["2p_pres_actv_impr"] = {prefix .. "cette", prefix .. "cedite"}
end
irreg_conjugations["dīcō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "dīc")
make_perf(data, prefix .. "dīx")
make_supine(data, typeinfo, prefix .. "dict")
make_sigm(data, typeinfo, prefix .. "dīx")
-- Additional regular imperative.
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "2s_pres_actv_impr", prefix, "dīc", 1)
end
irreg_conjugations["dō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Latin first conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
typeinfo.subtypes.shorta = true
make_pres(data, typeinfo, prefix .. "d")
make_perf(data, prefix .. "ded")
make_supine(data, typeinfo, prefix .. "dat")
end
irreg_conjugations["dūcō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "dūc")
make_perf(data, prefix .. "dūx")
make_supine(data, typeinfo, prefix .. "duct")
make_sigm(data, typeinfo, prefix .. "dūx")
add_form(forms, "2s_pres_actv_impr", prefix, "dūc", 1)
end
irreg_conjugations["edō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "ed")
make_perf(data, prefix .. "ēd")
make_supine(data, typeinfo, {prefix .. "ēs", prefix .. "ēss", prefix .. "ēst"})
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, nil, "ēs", "ēst", nil, "ēstis", nil)
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, nil, {"ēssis", "ēsse"}, "ēstur", nil, nil, nil)
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "edim", "edīs", {"edit", "ēst"}, "edīmus", "edītis", "edint")
add_forms(forms, "impf_actv_subj", prefix, "ēssem", "ēssēs", "ēsset", "ēssēmus", "ēssētis", "ēssent")
-- Passive imperfective subjunctive
add_forms(forms, "impf_pasv_subj", prefix, "ēsser", {"ēssēris", "ēssēre"}, "ēssētur", "ēssēmur", "ēssēminī", "ēssentur")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ēs", "ēste")
add_23_forms(forms, "futr_actv_impr", prefix, "ēstō", "ēstō", "ēstōte", nil)
-- Passive imperative
add_23_forms(forms, "futr_pasv_impr", prefix, "ēstor", "ēstor", nil, nil)
add_form(forms, "2s_pres_pasv_impr", prefix, "ēsse")
-- Present infinitives
add_form(forms, "pres_actv_inf", prefix, "ēsse")
end
irreg_conjugations["ëdō"] = irreg_conjugations["edō"]
irreg_conjugations["eō"] = function(args, data, typeinfo)
local forms = data.forms
insert_if_not(data.categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
make_perf(data, {prefix .. "i", prefix .. "īv"})
make_supine(data, typeinfo, prefix .. "it")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, "eō", "īs", "it", "īmus", "ītis",
prefix == "prōd" and {"eunt", "īnunt"} or "eunt")
add_forms(forms, "impf_actv_indc", prefix, "ībam", "ībās", "ībat", "ībāmus", "ībātis", "ībant")
add_forms(forms, "futr_actv_indc", prefix, "ībō", "ībis", "ībit", "ībimus", "ībitis", "ībunt")
-- Active perfective indicative
add_form(forms, "2s_perf_actv_indc", prefix, "īstī", 1)
add_form(forms, "2p_perf_actv_indc", prefix, "īstis", 1)
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, "eor", {"īris", "īre"}, "ītur", "īmur", "īminī", "euntur")
add_forms(forms, "impf_pasv_indc", prefix, "ībar", {"ībāris", "ībāre"}, "ībātur", "ībāmur", "ībāminī", "ībantur")
add_forms(forms, "futr_pasv_indc", prefix, "ībor", {"īberis", "ībere"}, "ībitur", "ībimur", "ībiminī", "ībuntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", prefix, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Active perfective subjunctive
add_form(forms, "1s_plup_actv_subj", prefix, "īssem", 1)
add_form(forms, "2s_plup_actv_subj", prefix, "īssēs", 1)
add_form(forms, "3s_plup_actv_subj", prefix, "īsset", 1)
add_form(forms, "1p_plup_actv_subj", prefix, "īssēmus", 1)
add_form(forms, "2p_plup_actv_subj", prefix, "īssētis", 1)
add_form(forms, "3p_plup_actv_subj", prefix, "īssent", 1)
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", prefix, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "impf_pasv_subj", prefix, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", prefix, "ītō", "ītō", "ītōte", "euntō")
add_2_forms(forms, "pres_pasv_impr", prefix, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", prefix, "ītor", "ītor", nil, "euntor")
-- Present infinitives
forms["pres_actv_inf"] = prefix .. "īre"
forms["pres_pasv_inf"] = prefix .. "īrī"
-- Perfect/future infinitives
add_form(forms, "perf_actv_inf", prefix, "īsse", 1)
-- Imperfective participles
forms["pres_actv_ptc"] = prefix .. "iēns"
-- Gerund
make_gerund(data, typeinfo, prefix .. "eund")
end
irreg_conjugations["ëō"] = irreg_conjugations["eō"]
local function fio(forms, prefix, voice)
-- Active/passive imperfective indicative
add_forms(forms, "pres_" .. voice .. "_indc", prefix,
"fīō", "fīs", "fit", "fīmus", "fītis", "fīunt")
add_forms(forms, "impf_" .. voice .. "_indc", prefix .. "fīēb",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_" .. voice .. "_indc", prefix .. "fī",
"am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperfective subjunctive
add_forms(forms, "pres_" .. voice .. "_subj", prefix .. "fī",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_" .. voice .. "_subj", prefix .. "fier",
"em", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperative
add_2_forms(forms, "pres_" .. voice .. "_impr", prefix .. "fī", "", "te")
add_23_forms(forms, "futr_" .. voice .. "_impr", prefix .. "fī", "tō", "tō", "tōte", "untō")
-- Active/passive present infinitive
add_form(forms, "pres_" .. voice .. "_inf", prefix, "fierī")
if voice == "actv" then
add_form(forms, "pres_actv_ptc", prefix, "fīēns")
end
end
irreg_conjugations["faciō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.suppl = true
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "fac")
-- Remove passive forms, except the gerund and future passive participle.
remove_forms(forms, {"pasv_indc", "pasv_subj", "pasv_impr", "pasv_inf"})
make_perf(data, prefix .. "fēc")
make_supine(data, typeinfo, prefix .. "fact")
make_sigm(data, typeinfo, prefix .. "fax")
if prefix == "" then
-- Active imperative
add_form(forms, "2s_pres_actv_impr", "", "fac", 1)
-- Sigmatic forms
add_form(forms, "1s_sigf_actv_indc", "", {"faxsō", "facsō", "faxiō"})
add_form(forms, "2s_sigf_actv_indc", "", {"faxsis", "facsis", "facxis", "facxsis"})
add_form(forms, "3s_sigf_actv_indc", "", "faxsit")
add_form(forms, "1p_sigf_actv_indc", "", "faxsimus")
add_form(forms, "2p_sigf_actv_indc", "", "faxsitis")
add_form(forms, "3p_sigf_actv_indc", "", "faxsint")
add_form(forms, "1s_siga_actv_subj", "", {"faxsim", "faxēm"})
add_form(forms, "2s_siga_actv_subj", "", {"faxsīs", "faxseis", "faxeis", "faxēs"})
add_form(forms, "3s_siga_actv_subj", "", {"faxsīt", "faxeit", "faxēt"})
add_form(forms, "1p_siga_actv_subj", "", {"faxsīmus", "faxeimus"})
add_form(forms, "2p_siga_actv_subj", "", {"faxsītis", "faxeitis"})
add_form(forms, "3p_siga_actv_subj", "", {"faxsint", "faxēnt"})
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "pres_actv_inf", "", "fāre")
data.form_footnote_indices["pres_actv_inf"] = tostring(noteindex)
data.footnotes[noteindex] = "Late Latin."
end
fio(forms, prefix, "pasv")
end
irreg_conjugations["ferō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.suppl = true
local prefix_pres = typeinfo.prefix or ""
local prefix_perf = ine(args[3])
local prefix_supine = ine(args[4])
prefix_perf = prefix_perf or prefix_pres
prefix_supine = prefix_supine or prefix_pres
make_pres(data, typeinfo, prefix_pres .. "fer")
if prefix_perf == "" then
make_perf(data, {"tul", "tetul"})
else
make_perf(data, prefix_perf .. "tul")
end
make_supine(data, typeinfo, prefix_supine .. "lāt")
-- Active imperfective indicative
forms["2s_pres_actv_indc"] = prefix_pres .. "fers"
forms["3s_pres_actv_indc"] = prefix_pres .. "fert"
forms["2p_pres_actv_indc"] = prefix_pres .. "fertis"
-- Passive imperfective indicative
forms["3s_pres_pasv_indc"] = prefix_pres .. "fertur"
-- Active imperfective subjunctive
forms["1s_impf_actv_subj"] = prefix_pres .. "ferrem"
forms["2s_impf_actv_subj"] = prefix_pres .. "ferrēs"
forms["3s_impf_actv_subj"] = prefix_pres .. "ferret"
forms["1p_impf_actv_subj"] = prefix_pres .. "ferrēmus"
forms["2p_impf_actv_subj"] = prefix_pres .. "ferrētis"
forms["3p_impf_actv_subj"] = prefix_pres .. "ferrent"
-- Passive present indicative
forms["2s_pres_pasv_indc"] = {prefix_pres .. "ferris", prefix_pres .. "ferre"}
-- Passive imperfective subjunctive
forms["1s_impf_pasv_subj"] = prefix_pres .. "ferrer"
forms["2s_impf_pasv_subj"] = {prefix_pres .. "ferrēris", prefix_pres .. "ferrēre"}
forms["3s_impf_pasv_subj"] = prefix_pres .. "ferrētur"
forms["1p_impf_pasv_subj"] = prefix_pres .. "ferrēmur"
forms["2p_impf_pasv_subj"] = prefix_pres .. "ferrēminī"
forms["3p_impf_pasv_subj"] = prefix_pres .. "ferrentur"
-- Imperative
forms["2s_pres_actv_impr"] = prefix_pres .. "fer"
forms["2p_pres_actv_impr"] = prefix_pres .. "ferte"
forms["2s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["3s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["2p_futr_actv_impr"] = prefix_pres .. "fertōte"
forms["2s_pres_pasv_impr"] = prefix_pres .. "ferre"
forms["2s_futr_pasv_impr"] = prefix_pres .. "fertor"
forms["3s_futr_pasv_impr"] = prefix_pres .. "fertor"
-- Present infinitives
forms["pres_actv_inf"] = prefix_pres .. "ferre"
forms["pres_pasv_inf"] = prefix_pres .. "ferrī"
if prefix_perf == "" then
local noteindex = table_len(data.footnotes) + 1
for slot, form in pairs(forms) do
if type(form) == "table" then
for _, f in ipairs(form) do
if f:match("^tetul") then
data.form_footnote_indices[slot] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
break
end
end
end
end
end
end
irreg_conjugations["fīō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin third conjugation verbs")
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.semidepon = true
subtypes.nofutractvptc = true
if not subtypes.nosup then
subtypes.suppl = true
end
local prefix = typeinfo.prefix or ""
fio(forms, prefix, "actv")
make_supine(data, typeinfo, prefix .. "fact")
forms["futr_actv_inf"] = forms["futr_pasv_inf"]
-- Gerund
make_gerund(data, typeinfo, prefix .. "fīend")
end
irreg_conjugations["inquam"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin defective verbs")
subtypes.highlydef = true
forms["1s_pres_actv_indc"] = "inquam"
forms["2s_pres_actv_indc"] = "inquis"
forms["3s_pres_actv_indc"] = "inquit"
forms["1p_pres_actv_indc"] = "inquimus"
forms["2p_pres_actv_indc"] = "inquitis"
forms["3p_pres_actv_indc"] = "inquiunt"
forms["2s_futr_actv_indc"] = "inquiēs"
forms["3s_futr_actv_indc"] = "inquiet"
forms["3p_futr_actv_indc"] = "inquient"
forms["3s_impf_actv_indc"] = "inquiēbat"
forms["1s_perf_actv_indc"] = "inquiī"
forms["2s_perf_actv_indc"] = "inquistī"
forms["3s_perf_actv_indc"] = "inquit"
forms["2s_pres_actv_subj"] = "inquiās"
forms["3s_pres_actv_subj"] = "inquiat"
forms["3p_pres_actv_subj"] = "inquiant"
forms["2s_pres_actv_impr"] = "inque"
forms["2s_futr_actv_impr"] = "inquitō"
forms["3s_futr_actv_impr"] = "inquitō"
forms["pres_actv_ptc"] = "inquiēns"
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Medieval Latin."
noteindex = tostring(noteindex)
data.form_footnote_indices["3p_futr_actv_indc"] = noteindex
data.form_footnote_indices["2s_pres_actv_subj"] = noteindex
data.form_footnote_indices["3p_pres_actv_subj"] = noteindex
end
-- Handle most forms of volō, mālō, nōlō.
local function volo_malo_nolo(forms, indc_stem, subj_stem, subtypes)
-- Present active indicative needs to be done individually as each
-- verb is different.
add_forms(forms, "impf_actv_indc", indc_stem .. "ēb", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", indc_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", subj_stem, "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", subj_stem .. "l", "em", "ēs", "et", "ēmus", "ētis", "ent")
-- Present infinitives
forms["pres_actv_inf"] = subj_stem .. "le"
-- Imperfective participles
forms["pres_actv_ptc"] = indc_stem .. "ēns"
subtypes.suppl = true
end
irreg_conjugations["mālō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.nopass = true
subtypes.noimp = true
make_perf(data, "mālu")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", "", "mālō", "māvīs", "māvult", "mālumus", "māvultis", "mālunt")
volo_malo_nolo(forms, "māl", "māl", subtypes)
end
irreg_conjugations["nōlō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.nopass = true
make_perf(data, "nōlu")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", "", "nōlō", "nōn vīs", "nōn vult", "nōlumus", "nōn vultis", "nōlunt")
add_forms(forms, "impf_actv_indc", "nōlēb", "am", "ās", "at", "āmus", "ātis", "ant")
volo_malo_nolo(forms, "nōl", "nōl", subtypes)
-- Imperative
add_2_forms(forms, "pres_actv_impr", "nōlī", "", "te")
add_23_forms(forms, "futr_actv_impr", "nōl", "itō", "itō", "itōte", "untō")
-- Additional Old Latin forms.
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", "", nil, "nevīs", {"nōn volt", "nevolt"}, nil, {"nōn voltis", "nōltis"}, nil)
data.form_footnote_indices["2s_pres_actv_indc"] = noteindex
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
end
irreg_conjugations["possum"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
subtypes.suppl = true
subtypes.passimpers = true
subtypes.passimpersold = true
make_perf(data, "potu")
-- Active imperfective indicative, impersonal passive
add_forms(forms, "pres_actv_indc", "", "possum", "potes", "potest", "possumus", "potestis", "possunt")
add_forms(forms, "impf_actv_indc", "poter", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", "poter", "ō", {"is", "e"}, "it", "imus", "itis", "unt")
forms["3s_pres_pasv_indc"] = "potestur"
forms["3s_impf_pasv_indc"] = "poterātur"
forms["3s_futr_pasv_indc"] = "poteritur"
-- Active imperfective subjunctive, impersonal passive
add_forms(forms, "pres_actv_subj", "poss", "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", "poss", "em", "ēs", "et", "ēmus", "ētis", "ent")
forms["3s_pres_pasv_subj"] = "possītur"
forms["3s_impf_pasv_subj"] = "possētur"
-- Present infinitives
forms["pres_actv_inf"] = {"posse", "potesse"}
-- Imperfective participles
forms["pres_actv_ptc"] = "potēns"
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin. The passive forms are only used to govern a passive infinitive; e.g. " .. mw.getCurrentFrame():preprocess("{{uxi|la|nec retrahi '''potestur''' imperiis|t=\"nor '''can it''' be withdrawn by commands\"}}") .. "."
noteindex = tostring(noteindex)
for slot in pairs(data.forms) do
if cfind(slot, "pasv") then
data.form_footnote_indices[slot] = noteindex
end
end
data.form_footnote_indices["pres_actv_inf"] = noteindex
end
-- The vowel of the prefix is lengthened if it ends in -n and the next word begins with f- or s-.
local function shorten_prefix(prefix)
return toNFC((ugsub(toNFD(prefix), "(" .. vowel .. ")" .. MACRON .. "n$", "%1n")))
end
local function lengthen_prefix(prefix)
return toNFC((ugsub(toNFD(prefix), "(" .. vowel .. ")" .. LENGTH .. "n$", "%1" .. MACRON .. "n")))
end
irreg_conjugations["sum"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
local prefix = typeinfo.prefix or ""
local prefix_e = ine(args[3]) or shorten_prefix(prefix)
local prefix_f = ine(args[4]) or lengthen_prefix(prefix)
local prefix_s = lengthen_prefix(prefix)
subtypes.suppl = true
subtypes.nopass = true
subtypes.supfutractvonly = true
make_perf(data, prefix_f .. "fu")
make_supine(data, typeinfo, prefix_f .. "fut")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix_s, "sum", nil, nil, "sumus", nil, "sunt")
add_forms(forms, "pres_actv_indc", prefix_e, nil, "es", "est", nil, "estis", nil)
add_forms(forms, "impf_actv_indc", prefix_e, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futr_actv_indc", prefix_e, "erō", {"eris", "ere"}, "erit", "erimus", "eritis", "erunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix_s, "sim", "sīs", "sit", "sīmus", "sītis", "sint")
add_forms(forms, "pres_actv_subj", prefix_s, "siem", "siēs", "siet", "siēmus", "siētis", "sient")
add_forms(forms, "pres_actv_subj", prefix_f, "fuam", "fuās", "fuat", "fuāmus", "fuātis", "fuant")
local noteindex = table_len(data.footnotes) + 1
for _, p in ipairs(persons) do
data.form_footnote_indices[p .. "_pres_actv_subj"] = tostring(noteindex)
end
data.footnotes[noteindex] = "Old Latin or in poetry."
if prefix_s == "ad" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_pres_actv_subj", "", "adessint", 2)
data.form_footnote_indices["3p_pres_actv_subj"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
end
add_forms(forms, "impf_actv_subj", prefix_e, "essem", "essēs", "esset", "essēmus", "essētis", "essent")
add_forms(forms, "impf_actv_subj", prefix_f, "forem", "forēs", "foret", "forēmus", "forētis", "forent")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix_e, "es", "este")
add_23_forms(forms, "futr_actv_impr", prefix_e, "estō", "estō", "estōte", nil)
add_form(forms, "3p_futr_actv_impr", prefix_s, "suntō")
-- Infinitives
add_form(forms, "pres_actv_inf", prefix_e, "esse")
add_form(forms, "futr_actv_inf", prefix_f, "fore")
-- Imperfective participles
if prefix == "ab" or prefix == "cōn" or prefix == "prae" or prefix == "præ" then
add_form(forms, "pres_actv_ptc", prefix_s, "sēns")
-- forms["pres_actv_ptc"] = prefix_s .. "sēns"
end
end
irreg_conjugations["volō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Latin irregular verbs")
insert_if_not(categories, "Latin suppletive verbs")
local prefix = typeinfo.prefix or ""
subtypes.nopass = true
subtypes.noimp = true
subtypes.supfutractvonly = true
make_perf(data, prefix .. "volu")
make_supine(data, typeinfo, prefix .. "volit")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, "volō", "vīs", "vult", "volumus", "vultis", "volunt")
volo_malo_nolo(forms, prefix .. "vol", prefix .. "vel", subtypes)
-- Additional Old Latin forms.
if prefix == "" then
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", prefix, nil, nil, "volt", nil, "voltis", nil)
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
-- vol- in the present subjunctive.
add_forms(forms, "pres_actv_subj", prefix .. "vol", "im", "īs", "it", "īmus", "ītis", "int")
for slot in pairs(data.forms) do
if cfind(slot, "pres_actv_subj") then
data.form_footnote_indices[slot] = noteindex
end
end
end
end
local function make_perfect_passive(data)
local forms = data.forms
local ppp = forms["perf_pasv_ptc"]
if type(ppp) ~= "table" then
ppp = {ppp}
end
local ppplinks = {}
for _, pppform in ipairs(ppp) do
insert(ppplinks, make_link(pppform, nil, "term"))
end
local ppplink = concat(ppplinks, " or ")
local sumlink = make_link("sum", nil, "term")
local text_for_slot = {
perf_pasv_indc = "present active indicative",
futp_pasv_indc = "future active indicative",
plup_pasv_indc = "imperfect active indicative",
perf_pasv_subj = "present active subjunctive",
plup_pasv_subj = "imperfect active subjunctive"
}
local passive_prefix, passive_suffix = data.passive_prefix, data.passive_suffix
local prefix_joiner = passive_prefix and passive_prefix:match(" $") and "+ " or ""
local suffix_joiner = passive_suffix and passive_suffix:match("^ ") and " +" or ""
for slot, text in pairs(text_for_slot) do
forms[slot] = (passive_prefix or "") .. prefix_joiner .. ppplink .. " + " ..
text .. " of " .. sumlink .. suffix_joiner .. (passive_suffix or "")
end
ppp = forms["1s_pres_actv_indc"]
if type(ppp) ~= "table" then
ppp = {ppp}
end
end
local function handle_deponent(data, subtypes)
local forms = data.forms
-- Generate a list of form types to remove.
local to_remove = {"pres_pasv_ptc", "futr_pasv_inf"}
if subtypes.depon then
insert(to_remove, "actv")
else
insert(to_remove, "pres_pasv")
insert(to_remove, "impf_pasv")
insert(to_remove, "futr_pasv")
if subtypes.semidepon then
insert(to_remove, "perf_actv")
insert(to_remove, "plup_actv")
insert(to_remove, "futp_actv")
end
end
-- Remove forms.
for slot in pairs(forms) do
if not (
slot == "futr_actv_inf" or
slot == "perp_actv_inf" or
slot == "pres_actv_ptc" or
slot == "futr_actv_ptc" or
slot == "futr_pasv_ptc"
) then
for _, part in ipairs(to_remove) do
if cfind(slot, part) then
forms[slot] = nil
break
end
end
end
end
-- Change passive to active, except for the future passive participle.
local changes = {}
for slot in pairs(forms) do
if cfind(slot, "pasv") and slot ~= "futr_pasv_ptc" then
changes[slot] = slot:gsub("pasv", "actv")
end
end
for old, new in pairs(changes) do
add_form(forms, new, "", forms[old])
forms[old] = nil
end
end
local function add_sync_perf(data, form, suf, note, noteindex)
local forms = data.forms
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local i = 0
while true do
i = i + 1
local stem = formval[i]
if not stem then
break
end
stem = stem:match("^(.*)" .. pattern_escape(suf) .. "$")
-- Can only syncopate "vi", "ve", "vē", or any one of them spelled with a "u" after a vowel.
-- TODO: Syncopate "si", "xi".
if stem then
local new_stem = toNFD(stem)
local vowel, loc, v, ei, diacritic = umatch(new_stem, "(" .. vowel .. "?)" .. LENGTH .. "()([uv])([ei])(" .. LENGTH .. ")$")
if loc and (v == "v" or vowel ~= "") and (ei == "e" or diacritic == "" or cfind(diacritic, BREVE)) then
new_stem = usub(new_stem, 1, loc - 1)
-- Can't be omitted if it's part of the first syllable.
if new_stem:match(vowel) then
i = i + 1
add_form(forms, form, new_stem, suf, i)
data.form_footnote_indices[form] = tostring(noteindex)
data.footnotes[noteindex] = note
end
end
end
end
end
local function has_no_infinitive(forms)
for slot in pairs(forms) do
if cfind(slot, "inf") and not form_is_empty(forms[slot]) then
return false
end
end
return true
end
local function has_no_gerund(forms)
if not form_is_empty(forms["futr_pasv_ptc"]) then
return false
end
for _, case in ipairs(ger_cases) do
if not form_is_empty(forms[case .. "_ger"]) then
return false
end
end
return true
end
local make_conjugation_mt = {}
function make_conjugation_mt:__call(args, data, typeinfo)
if typeinfo.irreg then
self.irreg(args, data, typeinfo)
else
get_regular_stems(args, typeinfo)
self[typeinfo.conj](args, data, typeinfo)
end
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
if subtypes.nopres or subtypes.perfaspres then
insert_if_not(categories, "Latin verbs with missing present stem")
insert_if_not(categories, "Latin defective verbs")
end
-- Maybe clear out the supine-derived forms (except maybe for the
-- future active participle). Do this first because some code below
-- looks at the perfect participle to derive other forms.
if subtypes.nosup then
-- Some verbs have no supine forms or forms derived from the supine
insert_if_not(categories, "Latin verbs with missing supine stem")
insert_if_not(categories, "Latin defective verbs")
forms["futr_actv_inf"] = nil
forms["futr_actv_ptc"] = nil
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
elseif subtypes.nofutractvptc then
-- Some verbs have a missing future active participle
insert_if_not(categories, "Latin verbs with supine stem with missing future active participle")
insert_if_not(categories, "Latin defective verbs")
forms["futr_actv_ptc"] = nil
forms["perp_actv_inf"] = nil
elseif subtypes.supfutractvonly then
-- Some verbs have no supine forms or forms derived from the supine,
-- except for the future active infinitive/participle
insert_if_not(categories, "Latin verbs with missing supine stem except in the future active participle")
insert_if_not(categories, "Latin defective verbs")
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
end
-- Add information for the passive perfective forms
if not (
form_is_empty(forms["perf_pasv_ptc"]) or
subtypes.optsemidepon or
subtypes.impers or
subtypes.passimpers and not (subtypes.depon or subtypes.semidepon or subtypes.optsemidepon) or
subtypes["3only"] or
subtypes.pass3only and not (subtypes.depon or subtypes.semidepon or subtypes.optsemidepon)
) then
make_perfect_passive(data)
end
-- Perfect forms as present tense.
if subtypes.perfaspres then
insert_if_not(categories, "Latin verbs with perfect forms used in the present tense")
-- Remove present active, imperfect active and future active forms and passive forms.
-- Change perfect forms to non-perfect forms.
local new_forms = {}
forms["futr_pasv_inf"] = nil
for slot, form in pairs(forms) do
if not (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
-- If semi-deponent, the perfect passive forms will be converted to perfect active.
if not (cfind(slot, "pasv") and (subtypes.semidepon or subtypes.optsemidepon)) then
slot = slot:gsub("perf", "pres")
:gsub("plup", "impf")
:gsub("futp", "futr")
end
new_forms[slot] = form
end
end
data.forms, forms = new_forms, new_forms
-- No present stem.
elseif subtypes.nopres then
for slot in pairs(forms) do
if (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
forms[slot] = nil
end
end
end
-- Types of irregularity related primarily to the active.
-- These could in theory be combined with those related to the passive and imperative,
-- i.e. there's no reason there couldn't be an impersonal deponent verb with no imperatives.
-- Deponent verbs use passive forms with active meaning.
if subtypes.depon then
insert_if_not(categories, "Latin deponent verbs")
handle_deponent(data, subtypes)
-- Semi-deponent verbs use perfective passive forms with active meaning,
-- and have no imperfective passive.
elseif subtypes.semidepon then
insert_if_not(categories, "Latin semi-deponent verbs")
handle_deponent(data, subtypes)
-- Optional semi-deponent verbs use perfective passive forms with active
-- meaning, but also have perfect active forms with the same meaning,
-- and have no imperfective passive.
elseif subtypes.optsemidepon then
insert_if_not(categories, "Latin semi-deponent verbs")
insert_if_not(categories, "Latin optionally semi-deponent verbs")
handle_deponent(data, subtypes)
elseif subtypes.noperf then
-- Some verbs have no perfect stem (e.g. inalbēscō, -ěre)
insert_if_not(categories, "Latin defective verbs")
if not subtypes.depon then
insert_if_not(categories, "Latin verbs with missing perfect stem")
end
-- Remove all active perfect forms (passive perfect forms may
-- still exist as they are formed with the supine stem)
for slot in pairs(forms) do
if cfind(slot, "actv") and (
cfind(slot, "perf") or
cfind(slot, "plup") or
cfind(slot, "futp")
) and slot ~= "futp_actv_inf" then
forms[slot] = nil
end
end
end
-- Handle the removal of any passive forms, including any impersonal/3rd-
-- person-only passives.
-- Third-person only.
if subtypes["3only"] then
insert_if_not(categories, "Latin third-person-only verbs")
for slot in pairs(forms) do
if slot:match("[12][sp]") then
forms[slot] = nil
end
end
-- Impersonal, so remove all non-third-person singular forms.
elseif subtypes.impers then
insert_if_not(categories, "Latin impersonal verbs")
for slot in pairs(forms) do
if slot:match("[12][sp]") or (
-- Keep third-person plural forms if third-person passive is set.
cfind(slot, "3p") and
not (subtypes.pass3only and cfind(slot, "pasv"))
) then
forms[slot] = nil
end
end
end
-- No passive forms.
if subtypes.nopass then
insert_if_not(categories, "Latin active-only verbs")
for slot in pairs(forms) do
if cfind(slot, "pasv") then
forms[slot] = nil
end
end
-- Only third person in the passive. For phrasal verbs with a plural
-- complement, also need to erase the 3s forms.
-- FIXME: handling of mp, fp and np needs to be done separately.
elseif subtypes.pass3only then
insert_if_not(categories, "Latin verbs with third-person passive")
local gender = data.gender
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
(gender == "mp" or gender == "fp" or gender == "np") and cfind(slot, "3s")
) then
forms[slot] = nil
end
end
-- Impersonal in the passive, so remove all passive non-third person forms.
elseif subtypes.passimpers then
insert_if_not(categories, "Latin verbs with impersonal passive")
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
cfind(slot, "3p")
) then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the imperative
if subtypes.noimp then
-- Some verbs have no imperatives
insert_if_not(categories, "Latin verbs with missing imperative")
insert_if_not(categories, "Latin defective verbs")
-- Remove all imperative forms
for slot in pairs(forms) do
if cfind(slot, "impr") then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the future
if subtypes.nofutr then
-- Some verbs (e.g. soleō) have no future
insert_if_not(categories, "Latin verbs with missing future")
insert_if_not(categories, "Latin defective verbs")
-- Remove all future forms
for slot in pairs(forms) do
if cfind(slot, "fut") then -- handles futr = future and futp = future perfect
forms[slot] = nil
end
end
end
local pres_stem = typeinfo.pres_stem
-- Add the ancient future_passive_participle of certain verbs
-- if pres_stem == "lāb" then
-- forms["futr_pasv_ptc"] = "lābundus"
-- elseif pres_stem == "collāb" then
-- forms["futr_pasv_ptc"] = "collābundus"
-- elseif pres_stem == "illāb" then
-- forms["futr_pasv_ptc"] = "illābundus"
-- elseif pres_stem == "relāb" then
-- forms["futr_pasv_ptc"] = "relābundus"
-- end
-- Add the poetic present passive infinitive forms of certain verbs
if subtypes.p3inf then
local form = "pres_" .. (subtypes.depon and "actv" or "pasv") .. "_inf"
local noteindex = table_len(data.footnotes) + 1
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
for i = 1, table_len(formval) do
insert(formval, usub(formval[i], 1, -2) .. "ier")
end
forms[form] = formval
data.form_footnote_indices[form] = tostring(noteindex)
data.footnotes[noteindex] = "The present passive infinitive in ''-ier'' is a rare poetic form which is attested."
end
--[==[
if subtypes.old2sgimp then
local form = "2s_pres_" .. (subtypes.depon and "actv" or "pasv") .. "_impr"
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local newvals = mw.clone(formval)
end]==]
-- Add the syncopated perfect forms, omitting the separately handled fourth conjugation cases.
if subtypes.poetsyncperf then
local noteindex, note = table_len(data.footnotes) + 1
if pres_stem and pres_stem:match("nōsc$") then
note = 'The verb "nōscō" and its compounds frequently drop the syllables "vi" and "ve" from their perfect, pluperfect and future perfect conjugations.'
else
note = "At least one rare poetic syncopated perfect form is attested."
end
-- infinitive
add_sync_perf(data, "perf_actv_inf", "sse", note, noteindex)
-- perfect actives
add_sync_perf(data, "2s_perf_actv_indc", "stī", note, noteindex)
add_sync_perf(data, "3s_perf_actv_indc", "t", note, noteindex)
add_sync_perf(data, "1p_perf_actv_indc", "mus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_indc", "stis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_indc", "runt", note, noteindex)
-- pluperfect actives
add_sync_perf(data, "1s_plup_actv_indc", "ram", note, noteindex)
add_sync_perf(data, "2s_plup_actv_indc", "rās", note, noteindex)
add_sync_perf(data, "3s_plup_actv_indc", "rat", note, noteindex)
add_sync_perf(data, "1p_plup_actv_indc", "rāmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_indc", "rātis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_indc", "rant", note, noteindex)
-- future perfect actives
add_sync_perf(data, "1s_futp_actv_indc", "rō", note, noteindex)
add_sync_perf(data, "2s_futp_actv_indc", "ris", note, noteindex)
add_sync_perf(data, "3s_futp_actv_indc", "rit", note, noteindex)
add_sync_perf(data, "1p_futp_actv_indc", "rimus", note, noteindex)
add_sync_perf(data, "2p_futp_actv_indc", "ritis", note, noteindex)
add_sync_perf(data, "3p_futp_actv_indc", "rint", note, noteindex)
-- perfect subjunctives
add_sync_perf(data, "1s_perf_actv_subj", "rim", note, noteindex)
add_sync_perf(data, "2s_perf_actv_subj", "rīs", note, noteindex)
add_sync_perf(data, "3s_perf_actv_subj", "rit", note, noteindex)
add_sync_perf(data, "1p_perf_actv_subj", "rīmus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_subj", "rītis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_subj", "rint", note, noteindex)
-- pluperfect subjunctives
add_sync_perf(data, "1s_plup_actv_subj", "ssem", note, noteindex)
add_sync_perf(data, "2s_plup_actv_subj", "ssēs", note, noteindex)
add_sync_perf(data, "3s_plup_actv_subj", "sset", note, noteindex)
add_sync_perf(data, "1p_plup_actv_subj", "ssēmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_subj", "ssētis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_subj", "ssent", note, noteindex)
end
if subtypes.syncfutractvptc then
-- TODO
end
-- Add category for sigmatic forms
if subtypes.sigm then
insert_if_not(categories, "Latin verbs with sigmatic forms")
-- Add subcategory for (very rare) passive sigmatic forms
if subtypes.sigmpasv then
insert_if_not(categories, "Latin verbs with passive sigmatic forms")
end
end
if subtypes.noinf then
-- Some verbs (e.g. inquam) have no infinitives
for slot in pairs(forms) do
if cfind(slot, "inf") then
forms[slot] = nil
end
end
end
if has_no_infinitive(forms) then
subtypes.noinf = true
insert_if_not(categories, "Latin verbs with missing infinitive")
insert_if_not(categories, "Latin defective verbs")
end
if subtypes.noger then
-- Some verbs (e.g. libet) have no gerund
forms["futr_pasv_ptc"] = nil
for _, case in ipairs(ger_cases) do
forms[case .. "_ger"] = nil
end
end
-- Catch verbs which don't have .noger explicitly specified.
if has_no_gerund(forms) then
subtypes.noger = true
insert_if_not(categories, "Latin verbs with missing gerund")
insert_if_not(categories, "Latin defective verbs")
end
if subtypes.imponly then
-- Some verbs only have imperatives
insert_if_not(categories, "Latin imperative-only verbs")
insert_if_not(categories, "Latin defective verbs")
-- Remove all non-imperative forms
for slot in pairs(forms) do
if not cfind(slot, "impr") then
forms[slot] = nil
end
end
end
end
setmetatable(make_conjugation, make_conjugation_mt)
-- Functions for generating the inflection table
-- Convert FORM (one or more forms) to a string of links. If the form is empty
-- (see form_is_empty), the return value will be "—".
local function show_form(formval, accel)
if not formval then
return "—"
elseif type(formval) ~= "table" then
formval = {formval}
elseif table_len(formval) == 0 then
return "—"
end
for slot, form in ipairs(formval) do
if form_is_empty(form) then
form = "—"
elseif form:match("%[%[.-]]") then
-- Don't put accelerators on forms already containing links such as
-- the perfect passive infinitive and future active infinitive, or
-- the participles wrongly get tagged as infinitives as well as
-- participles.
form = make_link(form)
else
form = make_link(form, nil, nil, accel)
end
formval[slot] = form
end
return concat(formval, ",<br> ")
end
local parts_to_tags = {
['1s'] = {'1', 's'},
['2s'] = {'2', 's'},
['3s'] = {'3', 's'},
['1p'] = {'1', 'p'},
['2p'] = {'2', 'p'},
['3p'] = {'3', 'p'},
['actv'] = {'act'},
['pasv'] = {'pass'},
['pres'] = {'pres'},
['impf'] = {'impf'},
['futr'] = {'fut'},
['perf'] = {'perf'},
['plup'] = {'plup'},
['futp'] = {'futp'},
['perp'] = {'perf', 'potn'},
['sigm'] = {'sigm'},
['sigf'] = {'sigm', 'fut'},
['siga'] = {'sigm', 'aor'},
['indc'] = {'ind'},
['subj'] = {'sub'},
['impr'] = {'imp'},
['inf'] = {'inf'},
['ptc'] = {'part'},
['ger'] = {'ger'},
['sup'] = {'sup'},
['nom'] = {'nom'},
['gen'] = {'gen'},
['dat'] = {'dat'},
['acc'] = {'acc'},
['abl'] = {'abl'},
}
-- Call show_form() the forms in each non-generic slot (where a
-- generic slot is something like pres_actv_indc that covers a whole
-- row of slots), converting the forms to a string consisting of
-- comma-separated links with accelerators in them.
local function convert_forms_into_links(data)
local accel_lemma, forms = data.actual_lemma[1], data.forms
for slot in iter_slots(false, false) do
local slot_parts = split(slot, "_")
local tags = {}
for _, part in ipairs(slot_parts) do
for _, tag in ipairs(parts_to_tags[part]) do
insert(tags, tag)
end
end
-- put the case first for verbal nouns
local accel = {form = concat(tags, "|"), lemma = accel_lemma}
forms[slot] = show_form(forms[slot], accel)
end
end
function export.get_valid_forms(raw_forms)
local valid_forms = {}
if raw_forms then
if type(raw_forms) ~= "table" then
raw_forms = {raw_forms}
end
for _, subform in ipairs(raw_forms) do
if not form_is_empty(subform) then
insert(valid_forms, subform)
end
end
end
return valid_forms
end
function export.get_lemma_forms(data, do_linked)
local linked_prefix, forms = do_linked and "linked_" or "", data.forms
for _, slot in ipairs(potential_lemma_slots) do
local lemma_forms = export.get_valid_forms(forms[linked_prefix .. slot])
if table_len(lemma_forms) > 0 then
return lemma_forms
end
end
return nil
end
local function get_displayable_lemma(lemma_forms)
if not lemma_forms then
return "—"
end
local lemma_links = {}
for _, subform in ipairs(lemma_forms) do
insert(lemma_links, make_link(nil, subform, "term"))
end
return concat(lemma_links, ", ")
end
local tenses_display = {
["pres"] = "present",
["impf"] = "imperfect",
["futr"] = "future",
["perf"] = "perfect",
["plup"] = "pluperfect",
["futp"] = "future perfect",
["perp"] = "perfect potential",
["sigf"] = "sigmatic future",
["siga"] = "sigmatic aorist"
}
local voices_display = {
["actv"] = "active",
["pasv"] = "passive",
}
local moods_display = {
["indc"] = "indicative",
["subj"] = "subjunctive",
["impr"] = "imperative",
}
--[[
local nonfins = {
["inf"] = "infinitives",
["ptc"] = "participles",
}
--]]
--[[
local verbalnouns = {
["ger"] = "gerund",
["sup"] = "supine",
}
--]]
--[[
local cases = {
["nom"] = "nominative",
["gen"] = "genitive",
["dat"] = "dative",
["acc"] = "accusative",
["abl"] = "ablative",
}
--]]
local function make_row(data, prefixes, headspan, cellspan, rowslot, rowname, class, fn)
local row = {}
if rowname then
insert(row, ('\n! class="%s"%s | %s%s'):format(class, headspan == 1 and "" or (' colspan="%d"'):format(headspan), rowname, fn or ""))
end
local has_row, forms = false, data.forms
if not form_is_empty(forms[rowslot]) then
if type(forms[rowslot]) == "table" then
if table_len(forms[rowslot]) > 1 then
error("Row slot " .. rowslot .. " cannot have more than one value.")
end
forms[rowslot] = forms[rowslot][1]
end
insert(row, '\n! colspan="12" class="roa-compound-row" |' .. forms[rowslot])
has_row = true
else
for _, prefix in ipairs(prefixes) do
local slot = prefix .. (rowslot and "_" .. rowslot or "")
insert(row, ('\n| colspan="%d" | '):format(cellspan) .. forms[slot] .. (
data.form_footnote_indices[slot] == nil and "" or
'<sup class="roa-red-superscript">' .. data.form_footnote_indices[slot] .. "</sup>"
))
if not form_is_empty(forms[slot]) then
has_row = true
end
end
end
return has_row and concat(row) or false
end
local function make_group(data, _tenses, voice, mood, class)
local group = {}
for _, tense in ipairs(_tenses) do
local fn = ""
if tense == "sigf" or tense == "siga" then
fn = data.form_footnote_indices["sigm"]
fn = fn and ('<sup class="roa-red-superscript">' .. fn .. "</sup>") or ""
end
local row = make_row(data, persons, 1, 2, tense .. "_" .. voice .. "_" .. mood, tenses_display[tense], class, fn)
if row then
insert(group, row)
end
end
return #group > 0 and ('\n|-\n! rowspan="' .. tostring(#group) .. '" class="' .. class .. '" | ' .. voices_display[voice] .. concat(group, "\n|-")) or false
end
local function make_section(data, mood, _tenses)
local section, name = {}, moods_display[mood]
local class = "roa-" .. name .. "-left-rail"
for _, voice in ipairs(voices) do
local group = make_group(data, _tenses, voice, mood, class)
if group then
insert(section, group)
end
end
if #section == 0 then
return ""
end
return (([=[
|-
! colspan="2" rowspan="2" class="%CLASS" | %NAME
! colspan="6" class="%CLASS" | ''singular''
! colspan="6" class="%CLASS" | ''plural''
|-
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]]=]):gsub("%%%u+", function(m)
return m == "%NAME" and name or m == "%CLASS" and class or m
end)) .. concat(section)
end
local function make_indc_rows(data)
return make_section(data, "indc", indc_tenses)
end
local function make_subj_rows(data)
return make_section(data, "subj", subj_tenses)
end
local function make_impr_rows(data)
return make_section(data, "impr", impr_tenses)
end
local function get_nonfin_cells(t)
local cells = {}
for _, f in ipairs{"inf", "ptc"} do
for _, v in ipairs(voices) do
insert(cells, t .. "_" .. v .. "_" .. f)
end
end
return cells
end
local function make_nonfin_rows(data)
local nonfin = {}
for _, t in ipairs(nonfin_tenses) do
local row = make_row(data, get_nonfin_cells(t), 2, 3, nil, tenses_display[t], "roa-nonfinite-header")
if row then
insert(nonfin, row)
end
end
if #nonfin == 0 then
return ""
end
return [=[
|-
! colspan="2" rowspan="2" class="roa-nonfinite-header" | non-finite forms
! colspan="6" class="roa-nonfinite-header" | infinitive
! colspan="6" class="roa-nonfinite-header" | participle
|-
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
|-]=] .. concat(nonfin, "\n|-")
end
local function make_vn_rows(data)
local vn = make_row(data, {"gen_ger", "dat_ger", "acc_ger", "abl_ger", "acc_sup", "abl_sup"}, nil, 2, nil, nil, "roa-nonfinite-header")
if not vn then
return ""
end
return [=[
|-
! colspan="2" rowspan="3" class="roa-nonfinite-header" | verbal nouns
! colspan="8" class="roa-nonfinite-header" | gerund
! colspan="4" class="roa-nonfinite-header" | supine
|-
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | genitive
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | dative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
|-]=] .. vn
end
local function make_footnotes(data)
local tbl, i = {}, 0
for k, v in pairs(data.footnotes) do
i = i + 1
tbl[i] = '<sup class="roa-red-superscript">' .. tostring(k) .. '</sup>' .. v .. '<br>'
end
return concat(tbl)
end
-- Make the table
local function make_table(data)
data.actual_lemma = export.get_lemma_forms(data)
convert_forms_into_links(data)
local title = data.title
return require("Module:TemplateStyles")("Module:roa-verb/style.css") .. [=[
<div class="NavFrame">
<div class="NavHead"> Conjugation of ]=] .. get_displayable_lemma(data.actual_lemma) .. (table_len(title) > 0 and " (" .. concat(title, ", ") .. ")" or "") .. [=[</div>
<div class="NavContent">
{| class="roa-inflection-table" data-toggle-category="inflection"
]=] .. make_indc_rows(data) .. make_subj_rows(data) .. make_impr_rows(data) .. make_nonfin_rows(data) .. make_vn_rows(data) .. [=[
|}</div></div>]=].. make_footnotes(data)
end
local function checkexist(data)
if NAMESPACE ~= "" then
return
end
local outerbreak = false
local categories = data.categories
for _, conjugation in pairs(data.forms) do
if conjugation then
if type(conjugation) ~= "table" then
conjugation = {conjugation}
end
for _, conj in ipairs(conjugation) do
if not cfind(conj, " ") and not cfind(conj, "[") then
local physical_page = lang:logicalToPhysical(lang:stripDiacritics(conj))
local t = mw.title.new(physical_page)
if t and not t:getContent() then
insert_if_not(categories, "Latin verbs with red links in their inflection tables")
outerbreak = true
break
end
end
end
end
if outerbreak then
break
end
end
end
-- functions for creating external search hyperlinks
local function cleanup(x)
x:gsub("[[%]]", "")
:gsub(" ", "+")
return toNFC((ugsub(toNFD(x), "[^%w]+", "")))
end
local function flatten_values(t)
t = flatten(t)
local i = 1
while true do
local v = t[i]
if v == nil then
return t
elseif cfind(v, "<") then
remove(t, i)
else
t[i] = cleanup(v)
i = i + 1
end
end
end
local function link_google_books(verb, forms, domain)
local function partition_XS_into_N(XS, N)
local count = 0
local mensae = {}
for _, v in pairs(XS) do
if count % N == 0 then
mensae[#mensae+1] = {}
end
count = count + 1
mensae[#mensae][#(mensae[#mensae])+1] = v
end
return mensae
end
local function forms_N_to_link(fs, N, args, site)
return '[https://www.google.com/search?'..args..'&q='..site..'+%22'.. concat(fs, "%22+OR+%22") ..'%22 '..N..']'
end
local function make_links_txt(fs, N, site)
local args = site == "Books" and "tbm=bks&lr=lang_la" or ""
local links = {}
for k,v in pairs(partition_XS_into_N(fs, N)) do
links[#links+1] = forms_N_to_link(v,k,args,site=="Books" and "" or site)
end
return concat(links, ' - ')
end
return "Google "..domain.." forms of "..verb.." : "..make_links_txt(forms, 30, domain)
end
-- The main new entry point.
function export.show(frame)
local parent_args = frame:getParent().args
local data, typeinfo = export.make_data(parent_args)
if type(data) == "string" then -- json=1 specified
return data
end
local domain = frame:getParent().args['search']
-- Test code to compare existing module to new one.
if test_new_la_verb_module then
local m_new_la_verb = require("Module:User:Benwing2/la-verb")
local miscdata = {
title = data.title,
categories = data.categories,
}
local new_parent_args = frame:getParent().args
local newdata = m_new_la_verb.make_data(new_parent_args)
local newmiscdata = {
title = newdata.title,
categories = newdata.categories,
}
local all_verb_props = {"forms", "form_footnote_indices", "footnotes", "miscdata"}
local difconj = false
for _, prop in ipairs(all_verb_props) do
local table = prop == "miscdata" and miscdata or data[prop]
local newtable = prop == "miscdata" and newmiscdata or newdata[prop]
for key, val in pairs(table) do
local newval = newtable[key]
if not forms_equal(val, newval) then
-- Uncomment this to display the particular key and
-- differing forms.
-- error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
if difconj then
break
end
-- Do the comparison the other way as well in case of extra keys
-- in the new table.
for key, newval in pairs(newtable) do
local val = table[key]
if not forms_equal(val, newval) then
-- Uncomment this to display the particular key and
-- differing forms.
-- error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
if difconj then
break
end
end
track(difconj and "different-conj" or "same-conj")
end
if typeinfo.subtypes.suffix then
data.categories = {}
end
-- Check if the links to the verb forms exist
-- Has to happen after other categories are removed for suffixes
checkexist(data)
if domain == nil then
return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end
local verb = data['forms']['1s_pres_actv_indc'] ~= nil and ('[[' .. toNFC((ugsub(toNFD(data['forms']['1s_pres_actv_indc']), '[^%w]+', ""))) .. '|' .. data['forms']['1s_pres_actv_indc'] .. ']]') or 'verb'
return link_google_books(verb, flatten_values(data['forms']), domain)
end
return export
tfvg6og460gshmrlspyomiicf68wdw4
344381
344379
2026-05-25T23:17:50Z
Hakimi97
2668
344381
Scribunto
text/plain
-- TODO:
-- 1. (DONE) detect_decl_and_subtypes doesn't do anything with perf_stem or supine_stem.
-- 2. (DONE) Should error on bad subtypes.
-- 3. Make sure Google Books link still works.
-- 4. (DONE) Add 4++ that has alternative perfects -īvī/-iī.
-- 5. (DONE) If sup but no perf, allow passive perfect forms.
-- 6. (DONE) Remove no-actv-perf.
-- 7. (DONE) Support plural prefix/suffix and plural passive prefix/suffix
-- 8. Delegate title line generation to [[Module:la-headword]].
-- 9. Automatic forms of slots which depend on the values of other slots should take into account overrides on the other slot:
-- futr_actv_ptc: determines futr_actv_inf and perp_actv_inf
-- perf_pasv_ptc: determines perf_pasv_indc, plup_pasv_indc, futp_pasv_indc, perf_pasv_inf and futp_pasv_inf (with changes if deponent/semideponent etc)
-- acc_sup: determines futr_pasv_inf (and futr_actv_inf if there's no futr_pasv_ptc)
-- 10. Handle "revertor"-type: deponent in the present, but not in the perfect.
-- If enabled, compare this module with new version of module to make
-- sure all conjugations are the same.
local export = {}
local test_new_la_verb_module = false
local m_la_headword = require("Module:la-headword")
local m_la_nominal = require("Module:la-nominal")
local m_la_utilities = require("Module:la-utilities")
local m_links = require("Module:links")
local m_table = require("Module:table")
local m_utilities = require("Module:utilities")
local lang = require("Module:languages").getByCode("la")
local sc = require("Module:scripts").getByCode("Latn")
local allowed_subtypes = mw.loadData("Module:la-verb/data").allowed_subtypes
local PAGENAME = mw.loadData("Module:headword/data").pagename
local NAMESPACE = mw.title.getCurrentTitle().nsText
if NAMESPACE == "Rekonstruksi" then
PAGENAME = "*" .. PAGENAME
end
-- Conjugations are the functions that do the actual
-- conjugating by creating the forms of a basic verb.
-- They are defined further down.
local make_conjugation = {}
local add_form = m_la_utilities.add_form
local concat = table.concat
local do_generate_noun_forms = m_la_nominal.do_generate_noun_forms
local do_generate_adj_forms = m_la_nominal.do_generate_adj_forms
local dump = mw.dumpObject
local flatten = m_table.flatten
local form_contains = m_la_utilities.form_contains
local form_is_empty = m_la_utilities.form_is_empty
local forms_equal = m_la_utilities.forms_equal
local full_link = m_links.full_link
local insert = table.insert
local insert_if_not = m_table.insertIfNot
local ipairs = ipairs
local pairs = pairs
local pattern_escape = require("Module:string utilities").pattern_escape
local remove = table.remove
local remove_forms = m_la_utilities.remove_forms
local remove_links = m_links.remove_links
local split = mw.text.split
local table_len = m_table.length
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local tostring = tostring
local type = type
local u = mw.ustring.char
local ugsub = mw.ustring.gsub
local umatch = mw.ustring.match
local unpack = unpack or table.unpack -- Lua 5.2 compatibility
local usub = mw.ustring.sub
local MACRON = u(0x304)
local BREVE = u(0x306)
local TREMA = u(0x308)
local LENGTH = MACRON .. "?" .. BREVE .. "?" .. TREMA .. "?"
local vowel = "[aeiouyAEIOUY]"
local generic_slots = {}
local non_generic_slots = {}
local potential_lemma_slots = {
"1s_pres_actv_indc", -- regular
"3s_pres_actv_indc", -- impersonal
"1s_perf_actv_indc", -- "coepī"
"3s_perf_actv_indc", -- doesn't occur?
"2s_pres_actv_impr", -- "cedo"
}
local persons = {"1s", "2s", "3s", "1p", "2p", "3p"}
local persons_2 = {"2s", "2p"}
local persons_23 = {"2s", "3s", "2p", "3p"}
local function handle_person(t, v, mood)
local non_pers_slot = t .. "_" .. v .. "_" .. mood
insert(generic_slots, non_pers_slot)
for _, p in ipairs(persons) do
insert(non_generic_slots, p .. "_" .. non_pers_slot)
end
end
local voices = {"actv", "pasv"}
local indc_tenses = {"pres", "impf", "futr", "perf", "plup", "futp", "sigf"}
local subj_tenses = {"pres", "impf", "perf", "plup", "siga"}
local impr_tenses = {"pres", "futr"}
local nonfin_tenses = {"pres", "futr", "perf", "futp", "perp"}
for _, v in ipairs(voices) do
for _, t in ipairs(indc_tenses) do
handle_person(t, v, "indc")
end
for _, t in ipairs(subj_tenses) do
handle_person(t, v, "subj")
end
for _, t in ipairs(impr_tenses) do
handle_person(t, v, "impr")
end
for _, f in ipairs{"inf", "ptc"} do
for _, t in ipairs(nonfin_tenses) do
insert(non_generic_slots, t .. "_" .. v .. "_" .. f)
end
end
end
insert(non_generic_slots, "sigm_actv_inf")
local ger_cases = {"gen", "dat", "acc", "abl"}
for _, c in ipairs(ger_cases) do
insert(non_generic_slots, c .. "_ger")
end
local sup_cases = {"acc", "abl"}
for _, c in ipairs(sup_cases) do
insert(non_generic_slots, c .. "_sup")
end
local function track(page)
require("Module:debug").track("la-verb/" .. page)
end
-- Constant version of :find()
local function cfind(str, text)
return str:find(text, nil, true)
end
-- Used for testing differences between production and sandbox module; see `test_new_la_verb_module` arm in show().
-- Do not delete!
local function concat_vals(val)
if type(val) == "table" then
return table.concat(val, ",")
else
return val
end
end
local function make_link(page, display, face, accel)
return full_link({term = page, alt = display, lang = lang, sc = sc, accel = accel}, face)
end
-- Iterate over all the "slots" associated with a verb declension, where a slot
-- is e.g. 1s_pres_actv_indc (a non-generic slot), pres_actv_indc (a generic slot),
-- or linked_1s_pres_actv_indc (a linked slot). Only include the generic and/or linked
-- slots if called for.
local function iter_slots(include_generic, include_linked)
-- stage == 1: non-generic slots
-- stage == 2: generic slots
-- stage == 3: linked slots
local stage = 1
local slotnum = 0
local max_slotnum = table_len(non_generic_slots)
return function()
slotnum = slotnum + 1
if slotnum > max_slotnum then
slotnum = 1
stage = stage + 1
if stage == 2 then
if include_generic then
max_slotnum = table_len(generic_slots)
else
stage = stage + 1
end
end
if stage == 3 then
if include_linked then
max_slotnum = table_len(potential_lemma_slots)
else
stage = stage + 1
end
end
if stage > 3 then
return nil
end
end
if stage == 1 then
return non_generic_slots[slotnum]
elseif stage == 2 then
return generic_slots[slotnum]
end
return "linked_" .. potential_lemma_slots[slotnum]
end
end
local function ine(val)
if val == "" then
return nil
end
return val
end
-- Construct a simple one- or two-part link, which will be put through full_link later.
local function make_raw_link(page, display)
if page and display then
return "[[" .. page .. "|" .. display .. "]]"
elseif page then
return "[[" .. page .. "]]"
end
return display
end
local function split_prefix_and_base(lemma, main_verbs)
lemma = toNFD(lemma)
for _, main in ipairs(main_verbs) do
local orig_main = main
main = toNFD(main)
local main_pattern = pattern_escape(main)
local prefix = umatch(lemma, "^(.*)" .. main_pattern .. "$")
-- If `main` starts with a vowel and there's no macron or trema, try it with a trema iff it's preceded by a vowel.
if (
not prefix and
main:match("^" .. vowel) and
not umatch(main, "^.[" .. MACRON .. TREMA .. "]")
) then
main_pattern = pattern_escape((main:gsub("^.", "%0" .. TREMA)))
prefix = umatch(lemma, "^(.*" .. vowel .. LENGTH .. ")" .. main_pattern .. "$")
end
if prefix then
return toNFC(prefix), orig_main
end
end
require("Module:collation").sort(main_verbs, lang)
error(("Conjugation %s may only be used with %s, or a derived verb that ends with one of them"):format(
dump("irreg"), m_table.serialCommaJoin(main_verbs, {conj = "or", dontTag = true, dump = true})
))
end
-- Given an ending (or possibly a full regex matching the entire lemma, if
-- a regex group is present), return the base minus the ending, or nil if
-- the ending doesn't match.
local function extract_base(lemma, ending)
if cfind(ending, "(") then
return umatch(lemma, ending)
end
return umatch(lemma, "^(.*)" .. ending .. "$")
end
local function check_spec(lemma, spec, specified_subtypes)
local ending, subtypes, incompatible = unpack(spec)
if incompatible then
for _, subtype in ipairs(incompatible) do
if specified_subtypes[subtype] then
return
end
end
end
for _, subtype in ipairs(subtypes) do
-- A cancelled subtype will have the value false.
if specified_subtypes[subtype] == false then
return
end
end
local base = extract_base(lemma, ending)
if base then
return base, subtypes
end
end
-- Given ENDINGS_AND_SUBTYPES (a list of pairs of endings with associated
-- subtypes, where each pair consists of a single ending spec and a list of
-- subtypes), check each ending in turn against LEMMA. If it matches, return
-- the pair BASE, SUBTYPES where BASE is the remainder of LEMMA minus the
-- ending, and SUBTYPES is the subtypes associated with the ending. If no
-- endings match, throw an error if DECLTYPE is non-nil, mentioning the
-- DECLTYPE (the user-specified declension); but if DECLTYPE is nil, just
-- return the pair nil, nil.
--
-- The ending spec in ENDINGS_AND_SUBTYPES is one of the following:
--
-- 1. A simple string, e.g. "ātur", specifying an ending.
-- 2. A regex that should match the entire lemma (it should be anchored at
-- the beginning with ^ and at the end with $), and contains a single
-- capturing group to match the base.
local function get_subtype_by_ending(lemma, conj, specified_subtypes, specs)
for _, spec in ipairs(specs) do
local base, subtypes = check_spec(lemma, spec, specified_subtypes)
if base then
return base, subtypes
end
end
if conj then
error("Unrecognized ending for conjugation " .. conj .. " verb: " .. lemma)
end
return nil, nil
end
local genders = {"m", "f", "n", "mp", "fp", "np"}
local irreg_verbs = {
"aiō",
"aiiō",
"aijō",
"ajō",
"cedo", -- final "o" not "ō"
"dīcō",
"dūcō",
"edō", -- FIXME: Will praedō cause problems?
"ëdō",
"dō", -- list after edō
"eō",
"ëō",
"faciō",
"ferō",
"fīō",
"inquam",
"mālō",
"nōlō",
"possum",
"sum",
"volō",
}
local irreg_verbs_conj = {
["aiō"] = "3rd-io",
["aiiō"] = "3rd-io",
["aijō"] = "3rd-io",
["ajō"] = "3rd-io",
["cedo"] = "irreg",
["dīcō"] = "3rd",
["dō"] = "1st",
["dūcō"] = "3rd",
["edō"] = "3rd",
["ëdō"] = "3rd",
["eō"] = "irreg",
["ëō"] = "irreg",
["faciō"] = "3rd-io",
["ferō"] = "3rd",
["fīō"] = "3rd",
["inquam"] = "irreg",
["mālō"] = "irreg",
["nōlō"] = "irreg",
["possum"] = "irreg",
["sum"] = "irreg",
["volō"] = "irreg",
}
local function detect_decl_and_subtypes(args)
local subtypes, specs = {}, split(args[1] or "", "%.")
local conj_arg = remove(specs, 1)
for _, spec in ipairs(specs) do
subtypes[spec:gsub("%-", "")] = spec:sub(1, 1) ~= "-"
end
local orig_lemma = toNFC(args[2] or PAGENAME)
local lemma = remove_links(orig_lemma)
local base, conj, irreg, detected_subtypes
local base_conj_arg, auto_perf_supine = conj_arg:match("^([1-4/]+)(%+%+?)$")
if base_conj_arg then
if (
(auto_perf_supine == "++" and not (base_conj_arg == "4")) or
(auto_perf_supine == "+" and not (base_conj_arg == "1" or base_conj_arg == "2" or base_conj_arg == "4"))
) then
error("Conjugation type " .. base_conj_arg .. auto_perf_supine .. " not allowed")
end
conj_arg = base_conj_arg
end
if orig_lemma:sub(1, 1) == "-" then
subtypes.suffix = true
end
local auto_perf, auto_supine, auto_sigm
if subtypes.sigmpasv then
subtypes.sigm = true
end
if subtypes.sigm then
auto_sigm = true
end
if conj_arg == "1" then
conj = "1st"
base, detected_subtypes = get_subtype_by_ending(lemma, "1", subtypes, {
{"ō", {}},
{"or", {"depon"}},
{"at", {"impers"}},
{"ātur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"ā", {"imponly"}},
{"āre", {"depon", "imponly"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
else
auto_perf = base .. "āv"
auto_supine = base .. "āt"
end
end
if auto_sigm then
auto_sigm = base .. "āss"
end
if subtypes.suffix then
subtypes.p3inf = true
end
elseif conj_arg == "2" then
conj = "2nd"
base, detected_subtypes = get_subtype_by_ending(lemma, "2", subtypes, {
{"eō", {}},
{"eor", {"depon"}},
{"et", {"impers"}},
{"ētur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"ē", {"imponly"}},
{"ēre", {"depon", "imponly"}},
})
if auto_perf_supine then
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
else
auto_perf = base .. "u"
auto_supine = base .. "it"
end
end
if auto_sigm then
auto_sigm = base .. "ēss"
end
elseif conj_arg == "3" or conj_arg == "3/4" then
base, detected_subtypes = get_subtype_by_ending(lemma, conj_arg == "3/4" and "3/4" or nil, subtypes, {
{"iō", {"i"}},
{"ior", {"depon", "i"}},
})
if base then
conj = conj_arg == "3/4" and "3rd/4th" or "3rd-io"
else
base, detected_subtypes = get_subtype_by_ending(lemma, "3", subtypes, {
{"ō", {}},
{"or", {"depon"}},
{"it", {"impers"}, {"nopres"}},
{"itur", {"depon", "impers"}},
{"ī", {"nopres"}},
{"it", {"nopres", "impers"}},
{"e", {"imponly"}, {"depon"}},
{"ere", {"depon", "imponly"}},
})
if subtypes.i then
conj = "3rd-io"
else
conj = "3rd"
end
end
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
end
if subtypes.suffix then
auto_perf = "-"
auto_supine = "-"
auto_sigm = "-"
end
elseif conj_arg == "4" then
conj = "4th"
base, detected_subtypes = get_subtype_by_ending(lemma, "4", subtypes, {
{"iō", {}},
{"ior", {"depon"}},
{"it", {"impers"}, {"nopres"}},
{"ītur", {"depon", "impers"}},
{"ī", {"nopres"}, {"imponly"}},
{"it", {"nopres", "impers"}},
{"ī", {"imponly"}},
{"īre", {"depon", "imponly"}},
})
if subtypes.nopres or subtypes.perfaspres or detected_subtypes.nopres then
auto_perf = base
elseif auto_perf_supine == "++" then
auto_perf = base .. "īv/" .. base .. "i"
auto_supine = base .. "īt"
elseif auto_perf_supine == "+" then
auto_perf = base .. "īv"
auto_supine = base .. "īt"
end
if auto_sigm then
auto_sigm = base .. "īss"
end
elseif conj_arg == "irreg" then
irreg = true
local prefix
prefix, base = split_prefix_and_base(lemma, irreg_verbs)
conj = irreg_verbs_conj[base]
args[1] = base
args[2] = prefix
-- args[3] and args[4] are used by ferō and sum and stay where they are
detected_subtypes = {}
else
error("Unrecognized conjugation: " .. dump(conj_arg))
end
for _, detected_subtype in ipairs(detected_subtypes) do
if detected_subtype == "impers" and subtypes["3only"] then
-- 3only overrides impers
elseif detected_subtype == "nopres" and subtypes.perfaspres then
-- perfaspres overrides nopres
else
subtypes[detected_subtype] = true
end
end
-- Get the gender of the verb's complement.
local gender
for _, g in ipairs(genders) do
if subtypes[g] then
if gender then
error(("Only one of the subtypes %s may be specified"):format(
m_table.serialCommaJoin(genders, {conj = "or", dontTag = true, dump = true})
))
end
gender = g
end
end
if not gender then
gender = (subtypes.impers or subtypes.passimpers or subtypes["3only"] or subtypes["pass3only"]) and "n" or "m"
end
if subtypes.nopres or subtypes.perfaspres then
subtypes.noger = true
end
if not irreg then
args[1] = base
local perf_stem, supine_stem
if subtypes.depon or subtypes.semidepon or subtypes.nopres or subtypes.perfaspres then
supine_stem = args[3] or auto_supine
if supine_stem == "-" and not subtypes.suffix then
supine_stem = nil
end
if not supine_stem then
if subtypes.depon or subtypes.semidepon then
subtypes.noperf = true
end
subtypes.nosup = true
end
if subtypes.sigm then
local sigm_stem = args[5] or auto_sigm
if sigm_stem == "-" and not subtypes.suffix then
sigm_stem = nil
end
args[5] = sigm_stem
end
args[2] = supine_stem
args[3] = nil
else
perf_stem = args[3] or auto_perf
if perf_stem == "-" and not subtypes.suffix then
perf_stem = nil
end
if not perf_stem then
subtypes.noperf = true
end
supine_stem = args[4] or auto_supine
if supine_stem == "-" and not subtypes.suffix then
supine_stem = nil
end
if not supine_stem then
subtypes.nosup = true
end
if subtypes.sigm then
local sigm_stem = args[5] or auto_sigm
if sigm_stem == "-" and not subtypes.suffix then
sigm_stem = nil
end
args[5] = sigm_stem
end
args[2] = perf_stem
args[3] = supine_stem
end
args[4] = nil
end
if auto_sigm and subtypes.depon then
subtypes.sigmpasv = true
end
for subtype in pairs(subtypes) do
if (
subtype == "i" and not (conj_arg == "3" or conj_arg == "3/4") or
not allowed_subtypes[subtype]
) then
error(("Unrecognized verb subtype %s for this conjugation"):format(dump(subtype)))
end
end
return conj, irreg, subtypes, orig_lemma, lemma, gender
end
local function _add_forms(forms, keytype, persons, stem, ...)
for i, p in ipairs(persons) do
local suf = select(i, ...)
if suf ~= nil then
add_form(forms, p .. "_" .. keytype, stem, suf)
end
end
end
-- Add a value to all persons/numbers of a given tense/voice/mood, e.g.
-- "pres_actv_indc" (specified by KEYTYPE). If a value is already present
-- in a key, it won't be added again.
--
-- The value for a given person/number combination is formed by concatenating
-- STEM and the appropriate suffix for that person/number, e.g. SUF1S. The
-- suffix can be a list, in which case STEM will be concatenated in turn to
-- each value in the list and all the resulting forms added to the key. To
-- not add a value for a specific person/number, specify nil or {} for the
-- suffix for the person/number.
local function add_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons, stem, ...)
end
-- Add a value to the 2nd person (singular and plural) of a given
-- tense/voice/mood. This works like add_forms().
local function add_2_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons_2, stem, ...)
end
-- Add a value to the 2nd and 3rd persons (singular and plural) of a given
-- tense/voice/mood. This works like add_forms().
local function add_23_forms(forms, keytype, stem, ...)
return _add_forms(forms, keytype, persons_23, stem, ...)
end
local function override(args, data)
local forms = data.forms
for slot in iter_slots(true, false) do
if args[slot] then
forms[slot] = split(args[slot], "/")
end
end
end
local function set_linked_forms(data, typeinfo)
-- Generate linked variants of slots that may be the lemma.
-- If the form is the same as the lemma (with links removed),
-- substitute the original lemma (with links included).
local forms = data.forms
for _, slot in ipairs(potential_lemma_slots) do
local formval = forms[slot]
local linked_forms = {}
if formval then
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form == typeinfo.lemma then
insert(linked_forms, typeinfo.orig_lemma)
else
insert(linked_forms, form)
end
end
end
forms["linked_" .. slot] = linked_forms
end
end
local function link_words_if_unlinked(affix)
return affix:match("%[%[.-]]") and affix or ugsub(affix, "%w+", "[[%0]]")
end
local function get_affix(data, key)
local affix = data[key] or ""
return link_words_if_unlinked(affix), remove_links(affix)
end
-- Add prefixes and suffixes to non-generic slots. The generic slots (e.g.
-- perf_pasv_indc, whose text indicates to use the past passive participle +
-- the present active indicative of [[sum]]), handle prefixes and suffixes
-- themselves in make_perfect_passive().
local function add_prefix_suffix(data)
if not data.prefix and not data.suffix then
return
end
local active_prefix, active_prefix_no_links = get_affix(data, "prefix")
local passive_prefix, passive_prefix_no_links = get_affix(data, "passive_prefix")
local plural_prefix, plural_prefix_no_links = get_affix(data, "plural_prefix")
local plural_passive_prefix, plural_passive_prefix_no_links = get_affix(data, "plural_passive_prefix")
local active_suffix, active_suffix_no_links = get_affix(data, "suffix")
local passive_suffix, passive_suffix_no_links = get_affix(data, "passive_suffix")
local plural_suffix, plural_suffix_no_links = get_affix(data, "plural_suffix")
local plural_passive_suffix, plural_passive_suffix_no_links = get_affix(data, "plural_passive_suffix")
local forms = data.forms
for slot in iter_slots(false, true) do
local prefix, suffix, prefix_no_links, suffix_no_links
if cfind(slot, "pasv") and slot:match("[123]p") then
prefix = plural_passive_prefix
suffix = plural_passive_suffix
prefix_no_links = plural_passive_prefix_no_links
suffix_no_links = plural_passive_suffix_no_links
elseif cfind(slot, "pasv") and not cfind(slot, "_inf") then
prefix = passive_prefix
suffix = passive_suffix
prefix_no_links = passive_prefix_no_links
suffix_no_links = passive_suffix_no_links
elseif slot:match("[123]p") then
prefix = plural_prefix
suffix = plural_suffix
prefix_no_links = plural_prefix_no_links
suffix_no_links = plural_suffix_no_links
else
prefix = active_prefix
suffix = active_suffix
prefix_no_links = active_prefix_no_links
suffix_no_links = active_suffix_no_links
end
local formval = forms[slot]
if not form_is_empty(formval) then
local affixed_forms = {}
if type(formval) ~= "table" then
formval = {formval}
end
for _, form in ipairs(formval) do
if form_is_empty(form) then
insert(affixed_forms, form)
elseif slot:match("^linked") then
-- If we're dealing with a linked slot, include the original
-- links in the prefix/suffix and also add a link around the
-- form itself if links aren't already present. (Note, above
-- we early-exited if there was no prefix and no suffix.)
if not form:match("%[%[.-]]") then
form = "[[" .. form .. "]]"
end
insert(affixed_forms, prefix .. form .. suffix)
elseif form:match("%[%[.-]]") then
-- If not dealing with a linked slot, but there are links
-- in the slot, include the original, potentially linked
-- versions of the prefix and suffix (e.g. in perfect
-- passive forms).
insert(affixed_forms, prefix .. form .. suffix)
else
-- Otherwise, use the non-linking versions of the prefix and
-- suffix so that the whole term (including prefix/suffix)
-- gets linked.
insert(affixed_forms, prefix_no_links .. form .. suffix_no_links)
end
end
forms[slot] = affixed_forms
end
end
end
local function notes_override(args, data)
local notes = {args["note1"], args["note2"], args["note3"]}
for n, note in pairs(notes) do
if note == "-" then
data.footnotes[n] = nil
elseif note == "p3inf" then
data.footnotes[n] = "The present passive infinitive in ''-ier'' is a rare poetic form which is attested."
elseif note == "poetsyncperf" then
data.footnotes[n] = "At least one rare poetic syncopated perfect form is attested."
elseif note == "sigm" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\")."
elseif note == "sigmpasv" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\"). It is also attested as having a rare sigmatic future passive indicative form (\"will have been\"), which is not attested in the plural for any verb."
elseif note == "sigmdepon" then
data.footnotes[n] = "At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense (which is not attested in the plural for any verb)."
elseif note then
data.footnotes[n] = note
end
end
if args["notes"] == "-" then
data.footnotes = {}
end
end
-- Space added by default; hyphens unchanged; underscore represents no space.
local affix_joining_chars = {
[""] = " ",
["-"] = "-",
["_"] = "",
}
local function normalize_prefix(prefix)
return prefix and prefix:gsub("[%-_]?$", affix_joining_chars, 1)
end
local function normalize_suffix(suffix)
return suffix and suffix:gsub("^[%-_]?", affix_joining_chars, 1)
end
local function handle_subtype_affix(args, affix, subtype_affix, normalize_func)
if args[subtype_affix] then
if not args[affix] then
error(("Can't specify %s= without %s="):format(subtype_affix, affix))
end
return normalize_func(args[subtype_affix])
end
end
local function handle_affix(args, data, affix, normalize_func)
data[affix] = normalize_func(args[affix])
for _, subtype in ipairs{"passive", "plural"} do
local subtype_affix = subtype .. "_" .. affix
data[subtype_affix] = handle_subtype_affix(args, affix, subtype_affix, normalize_func) or data[affix]
end
-- First fall back to the passive (e.g. "poenās dare", where the plural noun
-- is used with both singular and plural verbs, but there's a separate
-- passive form ''poenae datur''), then to the plural prefix, then to the
-- base prefix.
local subtype_affix = "plural_passive_" .. affix
data[subtype_affix] = handle_subtype_affix(args, affix, subtype_affix, normalize_func) or
data["passive_" .. affix] or data["plural_" .. affix] or data[affix]
end
function export.make_data(parent_args, from_headword, def1, def2)
local params = {
[1] = {required = true, default = def1 or "1+"},
[2] = {required = true, default = def2 or "amō"},
[3] = true,
[4] = true,
[5] = true,
prefix = true,
passive_prefix = true,
plural_prefix = true,
plural_passive_prefix = true,
suffix = true,
passive_suffix = true,
plural_suffix = true,
plural_passive_suffix = true,
label = true,
note1= true,
note2= true,
note3= true,
notes= true,
-- examined directly in export.show()
search = true,
json = {type = "boolean"},
}
for slot in iter_slots(true, false) do
params[slot] = true
end
if from_headword then
local list = {list = true}
params.lemma = list
params.id = true
params.cat = list
end
local args = require("Module:parameters").process(parent_args, params)
local conj, irreg, subtypes, orig_lemma, lemma, gender = detect_decl_and_subtypes(args)
-- note: the addition of red superscripted footnotes ('<sup class="roa-red-superscript">' ... </sup>) is only implemented for the three form printing loops in which it is used
local data = {
forms = {},
title = {},
categories = args.cat and m_table.deepCopy(args.cat) or {},
form_footnote_indices = {},
footnotes = {},
id = args.id,
overriding_lemma = args.lemma,
gender = gender,
}
local typeinfo = {
lemma = lemma,
orig_lemma = orig_lemma,
conj = conj,
irreg = irreg,
subtypes = subtypes,
}
handle_affix(args, data, "prefix", normalize_prefix)
handle_affix(args, data, "suffix", normalize_suffix)
-- Generate the verb forms
make_conjugation(args, data, typeinfo)
-- Generate the title text
m_la_headword.verb_title(data.title, typeinfo, export.get_lemma_forms(data))
-- Override with user-set forms
override(args, data)
-- Set linked_* forms
set_linked_forms(data, typeinfo)
-- Prepend any prefixes, append any suffixes
add_prefix_suffix(data)
if args["label"] then
insert_if_not(data.title, args["label"])
end
notes_override(args, data)
-- If json=1 specified, return a JSON string; used by bots
if args.json then
return require("Module:JSON").toJSON {
data = data,
typeinfo = typeinfo
}
end
return data, typeinfo
end
local ptc_lemma_form = {
["m"] = "sg_m",
["f"] = "sg_f",
["n"] = "sg_n",
["mp"] = "pl_m",
["fp"] = "pl_f",
["np"] = "pl_n",
}
-- Make the gerund and gerundive/future passive participle. For the forms
-- labeled "gerund", we generate both gerund and gerundive variants if there's
-- a case-specific prefix or suffix for the case in question; otherwise we
-- generate only the gerund per se. BASE is the stem (ending in -nd).
-- UND_VARIANT, if true, means that a gerundive in -und should be generated
-- along with a gerundive in -end.
local function make_gerund(data, typeinfo, base, und_variant)
local subtypes = typeinfo.subtypes
if subtypes.noger then
return
end
local forms, gender = data.forms, data.gender
local slot = "nom_" .. ptc_lemma_form[gender]
add_form(forms, "futr_pasv_ptc", "", do_generate_adj_forms({base .. "us<1&2+>"}, "participles", "bare").forms[slot])
if und_variant and not (subtypes.nound or base:match("[vV]end$") or umatch(base, "[uU]" .. LENGTH .. "end$")) then
-- Per Lane's grammar section 899: "Verbs in -ere and -īre often have
-- -undus, when not preceded by u or v, especially in formal style"
-- There is also an optional exclusion if -undus is not attested
add_form(forms, "futr_pasv_ptc", "", do_generate_adj_forms({base:gsub("end$", "und") .. "us<1&2+>"}, "participles", "bare").forms[slot])
end
local ger_forms = do_generate_noun_forms({base .. "um<2>"}, "nouns", "bare").forms
for _, case in ipairs(ger_cases) do
for _, form in ipairs(ger_forms[case .. "_sg"]) do
add_form(forms, case .. "_ger", "", form)
end
end
end
-- Conjugation functions
local function get_regular_stems(args, typeinfo)
local subtypes = typeinfo.subtypes
-- Get the parameters
if subtypes.nopres or subtypes.perfaspres then
typeinfo.pres_stem = nil
typeinfo.perf_stem = ine(args[1])
typeinfo.supine_stem = ine(args[2])
elseif subtypes.depon or subtypes.semidepon then
-- Deponent and semi-deponent verbs don't have the perfective principal part.
-- But optionally semi-deponent verbs do.
typeinfo.pres_stem = ine(args[1])
typeinfo.perf_stem = nil
typeinfo.supine_stem = ine(args[2])
else
typeinfo.pres_stem = ine(args[1])
typeinfo.perf_stem = ine(args[2])
typeinfo.supine_stem = ine(args[3])
end
if subtypes.sigm then
typeinfo.sigm_stem = ine(args[5])
end
-- Prepare stems
if not (typeinfo.pres_stem or subtypes.nopres or subtypes.perfaspres) then -- Template:
error("Present stem has not been provided")
end
if typeinfo.perf_stem then
typeinfo.perf_stem = split(typeinfo.perf_stem, "/")
else
typeinfo.perf_stem = {}
end
if typeinfo.supine_stem then
typeinfo.supine_stem = split(typeinfo.supine_stem, "/")
else
typeinfo.supine_stem = {}
end
if typeinfo.sigm_stem then
typeinfo.sigm_stem = split(typeinfo.sigm_stem, "/")
else
typeinfo.sigm_stem = {}
end
end
local function set_conj_categories(ord, data, typeinfo)
local categories, subtypes = data.categories, typeinfo.subtypes
insert_if_not(categories, "Kata kerja deponen konjugasi " .. ord .. " bahasa Latin")
if subtypes.depon then
insert_if_not(categories, "Latin " .. ord .. " conjugation deponent verbs")
end
if subtypes.noperf then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing perfect stem")
end
if subtypes.nosup then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem")
elseif subtypes.supfutractvonly then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with missing supine stem except in the future active participle")
end
local pres_stem = typeinfo.pres_stem
if not pres_stem then
return
end
pres_stem = pres_stem and pres_stem:gsub("[Qq]u", "\1")
for _, perf_stem in ipairs(typeinfo.perf_stem) do
perf_stem = perf_stem:gsub("[Qq]u", "\1")
if perf_stem == pres_stem .. "āv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -āv-")
elseif perf_stem == pres_stem .. "ēv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -ēv-")
elseif perf_stem == pres_stem .. "īv" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -īv-")
elseif perf_stem == pres_stem .. "i" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -i-")
elseif perf_stem == pres_stem .. "u" then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -u-")
elseif perf_stem == pres_stem then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with suffixless perfect")
elseif perf_stem:match("[sx]$") then
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with perfect in -s- or -x-")
else
insert_if_not(categories, "Latin " .. ord .. " conjugation verbs with irregular perfect")
end
end
end
-- Form-generating functions
local make_pres = {}
make_pres["1st"] = function(data, typeinfo, pres_stem)
local forms = data.forms
local a = typeinfo.subtypes.shorta and "a" or "ā"
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "ās", "at", a .. "mus", a .. "tis", "ant")
add_forms(forms, "impf_actv_indc", pres_stem, a .. "bam", a .. "bās", a .. "bat", a .. "bāmus", a .. "bātis", a .. "bant")
add_forms(forms, "futr_actv_indc", pres_stem, a .. "bō", a .. "bis", a .. "bit", a .. "bimus", a .. "bitis", a .. "bunt")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {a .. "ris", a .. "re"}, a .. "tur", a .. "mur", a .. "minī", "antur")
add_forms(forms, "impf_pasv_indc", pres_stem, a .. "bar", {a .. "bāris", a .. "bāre"}, a .. "bātur", a .. "bāmur", a .. "bāminī", a .. "bantur")
add_forms(forms, "futr_pasv_indc", pres_stem, a .. "bor", {a .. "beris", a .. "bere"}, a .. "bitur", a .. "bimur", a .. "biminī", a .. "buntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "em", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_subj", pres_stem, a .. "rem", a .. "rēs", a .. "ret", a .. "rēmus", a .. "rētis", a .. "rent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "er", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_subj", pres_stem, a .. "rer", {a .. "rēris", a .. "rēre"}, a .. "rētur", a .. "rēmur", a .. "rēminī", a .. "rentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ā", a .. "te")
add_23_forms(forms, "futr_actv_impr", pres_stem, a .. "tō", a .. "tō", a .. "tōte", "antō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, a .. "re", a .. "minī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, a .. "tor", a .. "tor", nil, "antor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, a .. "re")
add_form(forms, "pres_pasv_inf", pres_stem, a .. "rī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "āns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "and")
end
make_pres["2nd"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "eō", "ēs", "et", "ēmus", "ētis", "ent")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "ēbō", "ēbis", "ēbit", "ēbimus", "ēbitis", "ēbunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", pres_stem, "ērem", "ērēs", "ēret", "ērēmus", "ērētis", "ērent")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ē", "ēte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ētō", "ētō", "ētōte", "entō")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "eor", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ēbor", {"ēberis", "ēbere"}, "ēbitur", "ēbimur", "ēbiminī", "ēbuntur")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "ērer", {"ērēris", "ērēre"}, "ērētur", "ērēmur", "ērēminī", "ērentur")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ēre", "ēminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ētor", "ētor", nil, "entor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ēre")
add_form(forms, "pres_pasv_inf", pres_stem, "ērī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "ēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "end")
end
local function handle_old_impf(data, forms, pres_stem, ei, noteindex)
add_forms(forms, "impf_actv_indc", pres_stem .. ei, "bam", "bās", "bat", "bāmus", "bātis", "bant")
add_forms(forms, "impf_pasv_indc", pres_stem .. ei, "bar", {"bāris", "bāre"}, "bātur", "bāmur", "bāminī", "bantur")
for slot in pairs(data.forms) do
if cfind(slot, "impf") then
data.form_footnote_indices[slot] = noteindex
end
end
data.footnotes[noteindex] = "Pre-Classical."
end
local function handle_old_futr(data, forms, pres_stem, ei, noteindex)
add_forms(forms, "futr_actv_indc", pres_stem .. ei, "bō", "bis", "bit", "bimus", "bitis", "bunt")
add_forms(forms, "futr_pasv_indc", pres_stem .. ei, "bor", {"beris", "bere"}, "bitur", "bimur", "biminī", "buntur")
for slot in pairs(data.forms) do
if cfind(slot, "futr") then
data.form_footnote_indices[slot] = noteindex
end
end
data.footnotes[noteindex] = "Pre-Classical."
end
make_pres["3rd"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "ō", "is", "it", "imus", "itis", "unt")
add_forms(forms, "impf_actv_indc", pres_stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "or", {"eris", "ere"}, "itur", "imur", "iminī", "untur")
add_forms(forms, "impf_pasv_indc", pres_stem, "ēbar", {"ēbāris", "ēbāre"}, "ēbātur", "ēbāmur", "ēbāminī", "ēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "ar", {"ēris", "ēre"}, "ētur", "ēmur", "ēminī", "entur")
if typeinfo.subtypes.oldimpffutr then
handle_old_futr(data, forms, pres_stem, "ē", table_len(data.footnotes) + 1)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "ar", {"āris", "āre"}, "ātur", "āmur", "āminī", "antur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "untō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "untor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ere")
add_form(forms, "pres_pasv_inf", pres_stem, "ī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "ēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "end", "und-variant")
end
make_pres["3rd-io"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "is", "it", "imus", "itis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"eris", "ere"}, "itur", "imur", "iminī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "erem", "erēs", "eret", "erēmus", "erētis", "erent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "erer", {"erēris", "erēre"}, "erētur", "erēmur", "erēminī", "erentur")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "e", "ite")
add_23_forms(forms, "futr_actv_impr", pres_stem, "itō", "itō", "itōte", "iuntō")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, "ere", "iminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "itor", "itor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "ere")
add_form(forms, "pres_pasv_inf", pres_stem, "ī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
make_pres["3rd/4th"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "ī̆s", "it", "ī̆mus", "ī̆tis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"eris", "īris", "ere", "īre"}, "ī̆tur", "ī̆mur", "ī̆minī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, {"erem", "īrem"}, {"erēs", "īrēs"}, {"eret", "īret"}, {"erēmus", "īrēmus"}, {"erētis", "īrētis"}, {"erent", "īrent"})
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, {"erer", "īrer"}, {"erēris", "īrēris", "erēre", "īrēre"}, {"erētur", "īrētur"}, {"erēmur", "īrēmur"}, {"erēminī", "īrēminī"}, {"erentur", "īrentur"})
-- Active imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, {"e", "ī"}, "ī̆te")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ī̆tō", "ī̆tō", "ī̆tōte", "iuntō")
-- Passive imperative
add_2_forms(forms, "pres_pasv_impr", pres_stem, {"ere", "īre"}, "ī̆minī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ī̆tor", "ī̆tor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, {"ere", "īre"})
add_form(forms, "pres_pasv_inf", pres_stem, {"ī", "īrī"})
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
make_pres["4th"] = function(data, typeinfo, pres_stem)
local forms = data.forms
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", pres_stem, "iō", "īs", "it", "īmus", "ītis", "iunt")
add_forms(forms, "impf_actv_indc", pres_stem, "iēbam", "iēbās", "iēbat", "iēbāmus", "iēbātis", "iēbant")
add_forms(forms, "futr_actv_indc", pres_stem, "iam", "iēs", "iet", "iēmus", "iētis", "ient")
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", pres_stem, "ior", {"īris", "īre"}, "ītur", "īmur", "īminī", "iuntur")
add_forms(forms, "impf_pasv_indc", pres_stem, "iēbar", {"iēbāris", "iēbāre"}, "iēbātur", "iēbāmur", "iēbāminī", "iēbantur")
add_forms(forms, "futr_pasv_indc", pres_stem, "iar", {"iēris", "iēre"}, "iētur", "iēmur", "iēminī", "ientur")
if typeinfo.subtypes.oldimpffutr then
local noteindex = table_len(data.footnotes) + 1
handle_old_impf(data, forms, pres_stem, "ī", noteindex)
handle_old_futr(data, forms, pres_stem, "ī", noteindex)
end
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", pres_stem, "iam", "iās", "iat", "iāmus", "iātis", "iant")
add_forms(forms, "impf_actv_subj", pres_stem, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", pres_stem, "iar", {"iāris", "iāre"}, "iātur", "iāmur", "iāminī", "iantur")
add_forms(forms, "impf_pasv_subj", pres_stem, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", pres_stem, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", pres_stem, "ītō", "ītō", "ītōte", "iuntō")
add_2_forms(forms, "pres_pasv_impr", pres_stem, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", pres_stem, "ītor", "ītor", nil, "iuntor")
-- Present infinitives
add_form(forms, "pres_actv_inf", pres_stem, "īre")
add_form(forms, "pres_pasv_inf", pres_stem, "īrī")
-- Imperfective participles
add_form(forms, "pres_actv_ptc", pres_stem, "iēns")
-- Gerund
make_gerund(data, typeinfo, pres_stem .. "iend", "und-variant")
end
local make_pres_mt = {}
function make_pres_mt:__call(data, typeinfo, pres_stem)
if not pres_stem then
return
end
return self[typeinfo.conj](data, typeinfo, pres_stem)
end
setmetatable(make_pres, make_pres_mt)
local function make_perf(data, perf_stem, no_inf)
if not perf_stem then
return
end
local forms = data.forms
if type(perf_stem) ~= "table" then
perf_stem = {perf_stem}
end
for _, stem in ipairs(perf_stem) do
-- Perfective indicative
add_forms(forms, "perf_actv_indc", stem, "ī", "istī", "it", "imus", "istis", {"ērunt", "ēre"})
add_forms(forms, "plup_actv_indc", stem, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futp_actv_indc", stem, "erō", "eris", "erit", "erimus", "eritis", "erint")
-- Perfective subjunctive
add_forms(forms, "perf_actv_subj", stem, "erim", "erīs", "erit", "erīmus", "erītis", "erint")
add_forms(forms, "plup_actv_subj", stem, "issem", "issēs", "isset", "issēmus", "issētis", "issent")
-- Perfect infinitive
if not no_inf then
add_form(forms, "perf_actv_inf", stem, "isse")
end
end
end
local function make_true_supine(data, typeinfo, supine_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.supfutractvonly or not supine_stem then
return
end
local forms = data.forms
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
for _, stem in ipairs(supine_stem) do
local supine_forms = do_generate_noun_forms({stem .. "us<4>"}, "nouns", "bare").forms
add_form(forms, "acc_sup", "", supine_forms["acc_sg"])
add_form(forms, "abl_sup", "", supine_forms["abl_sg"])
add_form(forms, "futr_pasv_inf", forms["acc_sup"], " īrī")
if subtypes.nofutractvptc then
add_form(forms, "futr_actv_inf", forms["acc_sup"], " īre")
end
end
end
local function make_perf_pasv_ptc(data, typeinfo, supine_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.supfutractvonly or not supine_stem then
return
end
local forms, gender = data.forms
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
gender = "m" -- perf_pasv_ptc becomes perf_actv_ptc, so the gender of the complement isn't relevant
else
gender = data.gender
end
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
for _, stem in ipairs(supine_stem) do
-- Perfect passive participle
local perf_pasv_ptc_forms = do_generate_adj_forms({stem .. "us<1&2+>"}, "participles", "bare").forms
local form = perf_pasv_ptc_forms["nom_" .. ptc_lemma_form[gender]]
add_form(forms, "perf_pasv_ptc", "", form)
add_forms(forms, "perf_pasv_indc", form, " sum", " es", " est", nil, nil, nil)
add_forms(forms, "plup_pasv_indc", form, " eram", " erās", " erat", nil, nil, nil)
add_forms(forms, "futp_pasv_indc", form, " erō", " eris", " erit", nil, nil, nil)
add_forms(forms, "perf_pasv_subj", form, " sim", " sīs", " sit", nil, nil, nil)
add_forms(forms, "plup_pasv_subj", form, " essem", " essēs", " esset", nil, nil, nil)
form = perf_pasv_ptc_forms["nom_" .. ptc_lemma_form[gender]:gsub("sg", "pl")]
add_forms(forms, "perf_pasv_indc", form, nil, nil, nil, " sumus", " estis", " sunt")
add_forms(forms, "plup_pasv_indc", form, nil, nil, nil, " erāmus", " erātis", " erant")
add_forms(forms, "futp_pasv_indc", form, nil, nil, nil, " erimus", " eritis", " erint")
add_forms(forms, "perf_pasv_subj", form, nil, nil, nil, " sīmus", " sītis", " sint")
add_forms(forms, "plup_pasv_subj", form, nil, nil, nil, " essēmus", " essētis", " essent")
form = perf_pasv_ptc_forms["acc_" .. ptc_lemma_form[gender]]
add_form(forms, "perf_pasv_inf", form, " esse")
add_form(forms, "futp_pasv_inf", form, " fore")
end
end
-- A final "u" on the supine stem is omitted (e.g. "mortu" to "moritūrus").
local function make_futr_actv_ptc_stem(supine_stem)
local futr_actv_ptc_stem = {}
for _, stem in ipairs(supine_stem) do
insert(futr_actv_ptc_stem, (stem:gsub("u?$", "")))
end
return futr_actv_ptc_stem
end
local function make_futr_actv_ptc(data, typeinfo, futr_actv_ptc_stem)
local subtypes = typeinfo.subtypes
if subtypes.nosup or subtypes.nofutr or subtypes.nofutractvptc or not futr_actv_ptc_stem then
return
end
local forms = data.forms
if type(futr_actv_ptc_stem) ~= "table" then
futr_actv_ptc_stem = {futr_actv_ptc_stem}
end
for _, stem in ipairs(futr_actv_ptc_stem) do
local futr_actv_ptc_forms = do_generate_adj_forms({stem .. "ūrus<1&2+>"}, "participles", "bare").forms
add_form(forms, "futr_actv_ptc", "", futr_actv_ptc_forms["nom_sg_m"])
local form = futr_actv_ptc_forms["acc_sg_m"]
add_form(forms, "futr_actv_inf", form, " esse")
add_form(forms, "perp_actv_inf", form, " fuisse")
end
end
local function make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
if typeinfo.subtypes.nosup or not supine_stem then
return
end
make_true_supine(data, typeinfo, supine_stem)
make_perf_pasv_ptc(data, typeinfo, supine_stem)
if type(supine_stem) ~= "table" then
supine_stem = {supine_stem}
end
if futr_actv_ptc_stem == nil then
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
end
make_futr_actv_ptc(data, typeinfo, futr_actv_ptc_stem)
end
local function make_sigm(data, typeinfo, sigm_stem)
local subtypes = typeinfo.subtypes
if not subtypes.sigm then
return
end
local forms = data.forms
if type(sigm_stem) ~= "table" then
sigm_stem = {sigm_stem}
end
local noteindex = table_len(data.footnotes) + 1
-- Deponent verbs use the passive form
for _, stem in ipairs(sigm_stem) do
-- Sigmatic future active indicative
add_forms(forms, "sigf_actv_indc", stem, "ō", "is", "it", "imus", "itis", "int")
-- Sigmatic future passive indicative
if subtypes.sigmpasv then
add_forms(forms, "sigf_pasv_indc", stem, "or", "eris", "itur", nil, nil, nil) -- Plurals not attested.
end
-- Sigmatic future active subjunctive
add_forms(forms, "siga_actv_subj", stem, "im", "īs", "īt", "īmus", "ītis", "int")
-- Perfect infinitive
if not no_inf then
add_form(forms, "sigm_actv_inf", stem, "ere")
end
end
data.form_footnote_indices["sigm"] = noteindex
if subtypes.depon then
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" tense is attested, which is used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, and, as the verb is deponent, takes the form of what would otherwise be the rare sigmatic future passive indicative tense (which is not attested in the plural for any verb).'
else
data.footnotes[noteindex] = 'At least one use of the Old Latin \"sigmatic future\" and \"sigmatic aorist\" tenses is attested, which are used by [[Old Latin]] writers; most notably [[w:Plautus|Plautus]] and [[w:Terence|Terence]]. The sigmatic future is generally ascribed a future or future perfect meaning, while the sigmatic aorist expresses a possible desire (\"might want to\").'
if subtypes.sigmpasv then
data.footnotes[noteindex] = data.footnotes[noteindex] .. ' It is also attested as having a rare sigmatic future passive indicative form (\"will have been\"), which is not attested in the plural for any verb.'
end
end
end
make_conjugation["1st"] = function(args, data, typeinfo)
set_conj_categories("first", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
local forms = data.forms
if pres_stem == "dīlapid" then
add_form(forms, "3p_sigf_actv_indc", "", "dīlapidāssunt", 2)
elseif pres_stem == "invol" then
add_form(forms, "3s_sigf_actv_indc", "", "involāsit", 2)
elseif pres_stem == "viol" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_futp_actv_indc", "", "violārint", 2)
add_form(forms, "3p_perf_actv_subj", "", "violārint", 2)
add_form(forms, "3s_sigf_actv_indc", "", "violāsit", 2)
data.form_footnote_indices["3p_futp_actv_indc"] = tostring(noteindex)
data.form_footnote_indices["3p_perf_actv_subj"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
end
end
make_conjugation["2nd"] = function(args, data, typeinfo)
set_conj_categories("second", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if pres_stem == "noc" then
add_form(data.forms, "3s_siga_actv_subj", "", "noxsīt", 2)
end
end
make_conjugation["3rd"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
-- Additional forms in specific cases.
if not pres_stem then
return
elseif toNFD(pres_stem):match(vowel .. MACRON .. "sc$") then
insert_if_not(data.categories, "Latin inchoative verbs")
end
if pres_stem:match("nōsc$") then
typeinfo.subtypes.poetsyncperf = true
elseif pres_stem == "ulcīsc" then
local forms = data.forms
local formval = forms["1s_sigf_actv_indc"]
if type(formval) ~= "table" then
formval = {formval}
end
forms["1s_sigf_actv_indc"] = formval
local noteindex = table_len(data.footnotes) + 1
for i, form in ipairs(formval) do
if form == "ulsō" then
add_form(forms, "1s_sigf_actv_indc", "ull", "ō", i + 1)
data.form_footnote_indices["1s_sigf_actv_indc"] = tostring(noteindex)
data.footnotes[noteindex] = 'The form \"ullō\" may have resulted from a later, erroneous misreading of \"ulsō\".'
break
end
end
end
end
make_conjugation["3rd-io"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
local supine_stem, futr_actv_ptc_stem = typeinfo.supine_stem
if supine_stem then
local subtypes = typeinfo.subtypes
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
for i, stem in ipairs(futr_actv_ptc_stem) do
-- TODO: generalise this as a subtype which is automatic for 3rd-io verbs with -rt in the supine
local unsync_stem = stem:gsub("rt$", "rit")
futr_actv_ptc_stem[i] = unsync_stem
if unsync_stem ~= stem then
subtypes.syncfutractvptc = true
end
end
typeinfo.futr_actv_ptc_stem = futr_actv_ptc_stem
end
make_pres(data, typeinfo, typeinfo.pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
end
make_conjugation["3rd/4th"] = function(args, data, typeinfo)
set_conj_categories("third", data, typeinfo)
set_conj_categories("fourth", data, typeinfo)
local supine_stem, futr_actv_ptc_stem = typeinfo.supine_stem
if supine_stem then
local subtypes = typeinfo.subtypes
futr_actv_ptc_stem = make_futr_actv_ptc_stem(supine_stem)
for i, stem in ipairs(futr_actv_ptc_stem) do
-- TODO: generalise this as a subtype which is automatic for 3rd/4th verbs with -rt in the supine
local unsync_stem = stem:gsub("rt$", "rit")
futr_actv_ptc_stem[i] = unsync_stem
if unsync_stem ~= stem then
subtypes.syncfutractvptc = true
end
end
typeinfo.futr_actv_ptc_stem = futr_actv_ptc_stem
end
make_pres(data, typeinfo, typeinfo.pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, supine_stem, futr_actv_ptc_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
end
local function ivi_ive(form)
form = form:gsub("īvī", "iī")
form = form:gsub("īvi", "ī")
form = form:gsub("īve", "ī")
form = form:gsub("īvē", "ē")
return form
end
make_conjugation["4th"] = function(args, data, typeinfo)
set_conj_categories("fourth", data, typeinfo)
local pres_stem = typeinfo.pres_stem
make_pres(data, typeinfo, pres_stem)
make_perf(data, typeinfo.perf_stem)
make_supine(data, typeinfo, typeinfo.supine_stem)
make_sigm(data, typeinfo, typeinfo.sigm_stem)
local forms = data.forms
if form_contains(forms["1s_pres_actv_indc"], "serviō") or form_contains(forms["1s_pres_actv_indc"], "saeviō") then
add_forms(forms, "impf_actv_indc", pres_stem,
{"iēbam", "ībam"},
{"iēbās", "ībās"},
{"iēbat", "ībat"},
{"iēbāmus", "ībāmus"},
{"iēbātis", "ībātis"},
{"iēbant", "ībant"}
)
add_forms(forms, "futr_actv_indc", pres_stem,
{"iam", "ībō"},
{"iēs", "ībis"},
{"iet", "ībit"},
{"iēmus", "ībimus"},
{"iētis", "ībitis"},
{"ient", "ībunt"}
)
end
local subtypes = typeinfo.subtypes
if not (subtypes.alwayssyncperf or subtypes.optsyncperf) then
return
end
for key, formval in pairs(forms) do
if cfind(key, "perf") or cfind(key, "plup") or cfind(key, "futp") then
if type(formval) ~= "table" then
formval = {formval}
end
forms[key] = {}
for _, f in ipairs(formval) do
if subtypes.optsyncperf then
insert_if_not(forms[key], f)
end
insert_if_not(forms[key], ivi_ive(f))
end
end
end
end
-- Irregular conjugations.
local irreg_conjugations = {}
make_conjugation["irreg"] = function(args, data, typeinfo)
local verb = ine(args[1])
local prefix = ine(args[2])
if verb == nil then
error("The verb to be conjugated has not been specified.")
elseif not irreg_conjugations[verb] then
error(("Internal error: the irregular verb %s does not have a conjugation function specified."):format(dump(verb)))
end
typeinfo.prefix = prefix
-- Generate the verb forms
irreg_conjugations[verb](args, data, typeinfo)
end
for _, verb in ipairs{"aiō", "aiiō", "aijō", "ajō"} do
local stem = usub(verb, 1, -2)
local i_stem = stem:gsub("j$", "i")
irreg_conjugations[verb] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja hanya aktif bahasa Latin")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
subtypes.highlydef = true
subtypes.nopass = true
subtypes.nosup = true
stem = (typeinfo.prefix or "") .. stem
-- TODO: add period and frequency notes.
add_forms(forms, "pres_actv_indc", stem, "ō", "s", "t", nil, "tis", "unt")
add_forms(forms, "impf_actv_indc", stem, "ēbam", "ēbās", "ēbat", "ēbāmus", "ēbātis", "ēbant")
add_forms(forms, "perf_actv_indc", stem, nil, "stī", "t", nil, nil, {"ērunt", "ēre"})
add_forms(forms, "pres_actv_subj", stem, "am", "ās", "at", nil, nil, "ant")
add_form(forms, "3s_impf_actv_subj", stem, "eret")
add_form(forms, "2s_pres_actv_impr", stem, "")
add_form(forms, "pres_actv_inf", stem, "ere")
add_form(forms, "pres_actv_ptc", stem, "ēns")
end
end
irreg_conjugations["cedo"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
subtypes.imponly = true
subtypes.nofutr = true
subtypes.nopass = true
subtypes.noperf = true
subtypes.nosup = true
local prefix = typeinfo.prefix or ""
forms["2s_pres_actv_impr"] = prefix .. "cedo"
forms["2p_pres_actv_impr"] = {prefix .. "cette", prefix .. "cedite"}
end
irreg_conjugations["dīcō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "dīc")
make_perf(data, prefix .. "dīx")
make_supine(data, typeinfo, prefix .. "dict")
make_sigm(data, typeinfo, prefix .. "dīx")
-- Additional regular imperative.
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "2s_pres_actv_impr", prefix, "dīc", 1)
end
irreg_conjugations["dō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Latin first conjugation verbs")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
local prefix = typeinfo.prefix or ""
typeinfo.subtypes.shorta = true
make_pres(data, typeinfo, prefix .. "d")
make_perf(data, prefix .. "ded")
make_supine(data, typeinfo, prefix .. "dat")
end
irreg_conjugations["dūcō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "dūc")
make_perf(data, prefix .. "dūx")
make_supine(data, typeinfo, prefix .. "duct")
make_sigm(data, typeinfo, prefix .. "dūx")
add_form(forms, "2s_pres_actv_impr", prefix, "dūc", 1)
end
irreg_conjugations["edō"] = function(args, data, typeinfo)
local categories, forms = data.categories, data.forms
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "ed")
make_perf(data, prefix .. "ēd")
make_supine(data, typeinfo, {prefix .. "ēs", prefix .. "ēss", prefix .. "ēst"})
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, nil, "ēs", "ēst", nil, "ēstis", nil)
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, nil, {"ēssis", "ēsse"}, "ēstur", nil, nil, nil)
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "edim", "edīs", {"edit", "ēst"}, "edīmus", "edītis", "edint")
add_forms(forms, "impf_actv_subj", prefix, "ēssem", "ēssēs", "ēsset", "ēssēmus", "ēssētis", "ēssent")
-- Passive imperfective subjunctive
add_forms(forms, "impf_pasv_subj", prefix, "ēsser", {"ēssēris", "ēssēre"}, "ēssētur", "ēssēmur", "ēssēminī", "ēssentur")
-- Active imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ēs", "ēste")
add_23_forms(forms, "futr_actv_impr", prefix, "ēstō", "ēstō", "ēstōte", nil)
-- Passive imperative
add_23_forms(forms, "futr_pasv_impr", prefix, "ēstor", "ēstor", nil, nil)
add_form(forms, "2s_pres_pasv_impr", prefix, "ēsse")
-- Present infinitives
add_form(forms, "pres_actv_inf", prefix, "ēsse")
end
irreg_conjugations["ëdō"] = irreg_conjugations["edō"]
irreg_conjugations["eō"] = function(args, data, typeinfo)
local forms = data.forms
insert_if_not(data.categories, "Latin irregular verbs")
local prefix = typeinfo.prefix or ""
make_perf(data, {prefix .. "i", prefix .. "īv"})
make_supine(data, typeinfo, prefix .. "it")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, "eō", "īs", "it", "īmus", "ītis",
prefix == "prōd" and {"eunt", "īnunt"} or "eunt")
add_forms(forms, "impf_actv_indc", prefix, "ībam", "ībās", "ībat", "ībāmus", "ībātis", "ībant")
add_forms(forms, "futr_actv_indc", prefix, "ībō", "ībis", "ībit", "ībimus", "ībitis", "ībunt")
-- Active perfective indicative
add_form(forms, "2s_perf_actv_indc", prefix, "īstī", 1)
add_form(forms, "2p_perf_actv_indc", prefix, "īstis", 1)
-- Passive imperfective indicative
add_forms(forms, "pres_pasv_indc", prefix, "eor", {"īris", "īre"}, "ītur", "īmur", "īminī", "euntur")
add_forms(forms, "impf_pasv_indc", prefix, "ībar", {"ībāris", "ībāre"}, "ībātur", "ībāmur", "ībāminī", "ībantur")
add_forms(forms, "futr_pasv_indc", prefix, "ībor", {"īberis", "ībere"}, "ībitur", "ībimur", "ībiminī", "ībuntur")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix, "eam", "eās", "eat", "eāmus", "eātis", "eant")
add_forms(forms, "impf_actv_subj", prefix, "īrem", "īrēs", "īret", "īrēmus", "īrētis", "īrent")
-- Active perfective subjunctive
add_form(forms, "1s_plup_actv_subj", prefix, "īssem", 1)
add_form(forms, "2s_plup_actv_subj", prefix, "īssēs", 1)
add_form(forms, "3s_plup_actv_subj", prefix, "īsset", 1)
add_form(forms, "1p_plup_actv_subj", prefix, "īssēmus", 1)
add_form(forms, "2p_plup_actv_subj", prefix, "īssētis", 1)
add_form(forms, "3p_plup_actv_subj", prefix, "īssent", 1)
-- Passive imperfective subjunctive
add_forms(forms, "pres_pasv_subj", prefix, "ear", {"eāris", "eāre"}, "eātur", "eāmur", "eāminī", "eantur")
add_forms(forms, "impf_pasv_subj", prefix, "īrer", {"īrēris", "īrēre"}, "īrētur", "īrēmur", "īrēminī", "īrentur")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix, "ī", "īte")
add_23_forms(forms, "futr_actv_impr", prefix, "ītō", "ītō", "ītōte", "euntō")
add_2_forms(forms, "pres_pasv_impr", prefix, "īre", "īminī")
add_23_forms(forms, "futr_pasv_impr", prefix, "ītor", "ītor", nil, "euntor")
-- Present infinitives
forms["pres_actv_inf"] = prefix .. "īre"
forms["pres_pasv_inf"] = prefix .. "īrī"
-- Perfect/future infinitives
add_form(forms, "perf_actv_inf", prefix, "īsse", 1)
-- Imperfective participles
forms["pres_actv_ptc"] = prefix .. "iēns"
-- Gerund
make_gerund(data, typeinfo, prefix .. "eund")
end
irreg_conjugations["ëō"] = irreg_conjugations["eō"]
local function fio(forms, prefix, voice)
-- Active/passive imperfective indicative
add_forms(forms, "pres_" .. voice .. "_indc", prefix,
"fīō", "fīs", "fit", "fīmus", "fītis", "fīunt")
add_forms(forms, "impf_" .. voice .. "_indc", prefix .. "fīēb",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_" .. voice .. "_indc", prefix .. "fī",
"am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperfective subjunctive
add_forms(forms, "pres_" .. voice .. "_subj", prefix .. "fī",
"am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "impf_" .. voice .. "_subj", prefix .. "fier",
"em", "ēs", "et", "ēmus", "ētis", "ent")
-- Active/passive imperative
add_2_forms(forms, "pres_" .. voice .. "_impr", prefix .. "fī", "", "te")
add_23_forms(forms, "futr_" .. voice .. "_impr", prefix .. "fī", "tō", "tō", "tōte", "untō")
-- Active/passive present infinitive
add_form(forms, "pres_" .. voice .. "_inf", prefix, "fierī")
if voice == "actv" then
add_form(forms, "pres_actv_ptc", prefix, "fīēns")
end
end
irreg_conjugations["faciō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.suppl = true
local prefix = typeinfo.prefix or ""
make_pres(data, typeinfo, prefix .. "fac")
-- Remove passive forms, except the gerund and future passive participle.
remove_forms(forms, {"pasv_indc", "pasv_subj", "pasv_impr", "pasv_inf"})
make_perf(data, prefix .. "fēc")
make_supine(data, typeinfo, prefix .. "fact")
make_sigm(data, typeinfo, prefix .. "fax")
if prefix == "" then
-- Active imperative
add_form(forms, "2s_pres_actv_impr", "", "fac", 1)
-- Sigmatic forms
add_form(forms, "1s_sigf_actv_indc", "", {"faxsō", "facsō", "faxiō"})
add_form(forms, "2s_sigf_actv_indc", "", {"faxsis", "facsis", "facxis", "facxsis"})
add_form(forms, "3s_sigf_actv_indc", "", "faxsit")
add_form(forms, "1p_sigf_actv_indc", "", "faxsimus")
add_form(forms, "2p_sigf_actv_indc", "", "faxsitis")
add_form(forms, "3p_sigf_actv_indc", "", "faxsint")
add_form(forms, "1s_siga_actv_subj", "", {"faxsim", "faxēm"})
add_form(forms, "2s_siga_actv_subj", "", {"faxsīs", "faxseis", "faxeis", "faxēs"})
add_form(forms, "3s_siga_actv_subj", "", {"faxsīt", "faxeit", "faxēt"})
add_form(forms, "1p_siga_actv_subj", "", {"faxsīmus", "faxeimus"})
add_form(forms, "2p_siga_actv_subj", "", {"faxsītis", "faxeitis"})
add_form(forms, "3p_siga_actv_subj", "", {"faxsint", "faxēnt"})
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "pres_actv_inf", "", "fāre")
data.form_footnote_indices["pres_actv_inf"] = tostring(noteindex)
data.footnotes[noteindex] = "Late Latin."
end
fio(forms, prefix, "pasv")
end
irreg_conjugations["ferō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.suppl = true
local prefix_pres = typeinfo.prefix or ""
local prefix_perf = ine(args[3])
local prefix_supine = ine(args[4])
prefix_perf = prefix_perf or prefix_pres
prefix_supine = prefix_supine or prefix_pres
make_pres(data, typeinfo, prefix_pres .. "fer")
if prefix_perf == "" then
make_perf(data, {"tul", "tetul"})
else
make_perf(data, prefix_perf .. "tul")
end
make_supine(data, typeinfo, prefix_supine .. "lāt")
-- Active imperfective indicative
forms["2s_pres_actv_indc"] = prefix_pres .. "fers"
forms["3s_pres_actv_indc"] = prefix_pres .. "fert"
forms["2p_pres_actv_indc"] = prefix_pres .. "fertis"
-- Passive imperfective indicative
forms["3s_pres_pasv_indc"] = prefix_pres .. "fertur"
-- Active imperfective subjunctive
forms["1s_impf_actv_subj"] = prefix_pres .. "ferrem"
forms["2s_impf_actv_subj"] = prefix_pres .. "ferrēs"
forms["3s_impf_actv_subj"] = prefix_pres .. "ferret"
forms["1p_impf_actv_subj"] = prefix_pres .. "ferrēmus"
forms["2p_impf_actv_subj"] = prefix_pres .. "ferrētis"
forms["3p_impf_actv_subj"] = prefix_pres .. "ferrent"
-- Passive present indicative
forms["2s_pres_pasv_indc"] = {prefix_pres .. "ferris", prefix_pres .. "ferre"}
-- Passive imperfective subjunctive
forms["1s_impf_pasv_subj"] = prefix_pres .. "ferrer"
forms["2s_impf_pasv_subj"] = {prefix_pres .. "ferrēris", prefix_pres .. "ferrēre"}
forms["3s_impf_pasv_subj"] = prefix_pres .. "ferrētur"
forms["1p_impf_pasv_subj"] = prefix_pres .. "ferrēmur"
forms["2p_impf_pasv_subj"] = prefix_pres .. "ferrēminī"
forms["3p_impf_pasv_subj"] = prefix_pres .. "ferrentur"
-- Imperative
forms["2s_pres_actv_impr"] = prefix_pres .. "fer"
forms["2p_pres_actv_impr"] = prefix_pres .. "ferte"
forms["2s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["3s_futr_actv_impr"] = prefix_pres .. "fertō"
forms["2p_futr_actv_impr"] = prefix_pres .. "fertōte"
forms["2s_pres_pasv_impr"] = prefix_pres .. "ferre"
forms["2s_futr_pasv_impr"] = prefix_pres .. "fertor"
forms["3s_futr_pasv_impr"] = prefix_pres .. "fertor"
-- Present infinitives
forms["pres_actv_inf"] = prefix_pres .. "ferre"
forms["pres_pasv_inf"] = prefix_pres .. "ferrī"
if prefix_perf == "" then
local noteindex = table_len(data.footnotes) + 1
for slot, form in pairs(forms) do
if type(form) == "table" then
for _, f in ipairs(form) do
if f:match("^tetul") then
data.form_footnote_indices[slot] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
break
end
end
end
end
end
end
irreg_conjugations["fīō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja konjugasi ketiga bahasa Latin")
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.semidepon = true
subtypes.nofutractvptc = true
if not subtypes.nosup then
subtypes.suppl = true
end
local prefix = typeinfo.prefix or ""
fio(forms, prefix, "actv")
make_supine(data, typeinfo, prefix .. "fact")
forms["futr_actv_inf"] = forms["futr_pasv_inf"]
-- Gerund
make_gerund(data, typeinfo, prefix .. "fīend")
end
irreg_conjugations["inquam"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
subtypes.highlydef = true
forms["1s_pres_actv_indc"] = "inquam"
forms["2s_pres_actv_indc"] = "inquis"
forms["3s_pres_actv_indc"] = "inquit"
forms["1p_pres_actv_indc"] = "inquimus"
forms["2p_pres_actv_indc"] = "inquitis"
forms["3p_pres_actv_indc"] = "inquiunt"
forms["2s_futr_actv_indc"] = "inquiēs"
forms["3s_futr_actv_indc"] = "inquiet"
forms["3p_futr_actv_indc"] = "inquient"
forms["3s_impf_actv_indc"] = "inquiēbat"
forms["1s_perf_actv_indc"] = "inquiī"
forms["2s_perf_actv_indc"] = "inquistī"
forms["3s_perf_actv_indc"] = "inquit"
forms["2s_pres_actv_subj"] = "inquiās"
forms["3s_pres_actv_subj"] = "inquiat"
forms["3p_pres_actv_subj"] = "inquiant"
forms["2s_pres_actv_impr"] = "inque"
forms["2s_futr_actv_impr"] = "inquitō"
forms["3s_futr_actv_impr"] = "inquitō"
forms["pres_actv_ptc"] = "inquiēns"
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Medieval Latin."
noteindex = tostring(noteindex)
data.form_footnote_indices["3p_futr_actv_indc"] = noteindex
data.form_footnote_indices["2s_pres_actv_subj"] = noteindex
data.form_footnote_indices["3p_pres_actv_subj"] = noteindex
end
-- Handle most forms of volō, mālō, nōlō.
local function volo_malo_nolo(forms, indc_stem, subj_stem, subtypes)
-- Present active indicative needs to be done individually as each
-- verb is different.
add_forms(forms, "impf_actv_indc", indc_stem .. "ēb", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", indc_stem, "am", "ēs", "et", "ēmus", "ētis", "ent")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", subj_stem, "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", subj_stem .. "l", "em", "ēs", "et", "ēmus", "ētis", "ent")
-- Present infinitives
forms["pres_actv_inf"] = subj_stem .. "le"
-- Imperfective participles
forms["pres_actv_ptc"] = indc_stem .. "ēns"
subtypes.suppl = true
end
irreg_conjugations["mālō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.nopass = true
subtypes.noimp = true
make_perf(data, "mālu")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", "", "mālō", "māvīs", "māvult", "mālumus", "māvultis", "mālunt")
volo_malo_nolo(forms, "māl", "māl", subtypes)
end
irreg_conjugations["nōlō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.nopass = true
make_perf(data, "nōlu")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", "", "nōlō", "nōn vīs", "nōn vult", "nōlumus", "nōn vultis", "nōlunt")
add_forms(forms, "impf_actv_indc", "nōlēb", "am", "ās", "at", "āmus", "ātis", "ant")
volo_malo_nolo(forms, "nōl", "nōl", subtypes)
-- Imperative
add_2_forms(forms, "pres_actv_impr", "nōlī", "", "te")
add_23_forms(forms, "futr_actv_impr", "nōl", "itō", "itō", "itōte", "untō")
-- Additional Old Latin forms.
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", "", nil, "nevīs", {"nōn volt", "nevolt"}, nil, {"nōn voltis", "nōltis"}, nil)
data.form_footnote_indices["2s_pres_actv_indc"] = noteindex
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
end
irreg_conjugations["possum"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
subtypes.suppl = true
subtypes.passimpers = true
subtypes.passimpersold = true
make_perf(data, "potu")
-- Active imperfective indicative, impersonal passive
add_forms(forms, "pres_actv_indc", "", "possum", "potes", "potest", "possumus", "potestis", "possunt")
add_forms(forms, "impf_actv_indc", "poter", "am", "ās", "at", "āmus", "ātis", "ant")
add_forms(forms, "futr_actv_indc", "poter", "ō", {"is", "e"}, "it", "imus", "itis", "unt")
forms["3s_pres_pasv_indc"] = "potestur"
forms["3s_impf_pasv_indc"] = "poterātur"
forms["3s_futr_pasv_indc"] = "poteritur"
-- Active imperfective subjunctive, impersonal passive
add_forms(forms, "pres_actv_subj", "poss", "im", "īs", "it", "īmus", "ītis", "int")
add_forms(forms, "impf_actv_subj", "poss", "em", "ēs", "et", "ēmus", "ētis", "ent")
forms["3s_pres_pasv_subj"] = "possītur"
forms["3s_impf_pasv_subj"] = "possētur"
-- Present infinitives
forms["pres_actv_inf"] = {"posse", "potesse"}
-- Imperfective participles
forms["pres_actv_ptc"] = "potēns"
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin. The passive forms are only used to govern a passive infinitive; e.g. " .. mw.getCurrentFrame():preprocess("{{uxi|la|nec retrahi '''potestur''' imperiis|t=\"nor '''can it''' be withdrawn by commands\"}}") .. "."
noteindex = tostring(noteindex)
for slot in pairs(data.forms) do
if cfind(slot, "pasv") then
data.form_footnote_indices[slot] = noteindex
end
end
data.form_footnote_indices["pres_actv_inf"] = noteindex
end
-- The vowel of the prefix is lengthened if it ends in -n and the next word begins with f- or s-.
local function shorten_prefix(prefix)
return toNFC((ugsub(toNFD(prefix), "(" .. vowel .. ")" .. MACRON .. "n$", "%1n")))
end
local function lengthen_prefix(prefix)
return toNFC((ugsub(toNFD(prefix), "(" .. vowel .. ")" .. LENGTH .. "n$", "%1" .. MACRON .. "n")))
end
irreg_conjugations["sum"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
local prefix = typeinfo.prefix or ""
local prefix_e = ine(args[3]) or shorten_prefix(prefix)
local prefix_f = ine(args[4]) or lengthen_prefix(prefix)
local prefix_s = lengthen_prefix(prefix)
subtypes.suppl = true
subtypes.nopass = true
subtypes.supfutractvonly = true
make_perf(data, prefix_f .. "fu")
make_supine(data, typeinfo, prefix_f .. "fut")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix_s, "sum", nil, nil, "sumus", nil, "sunt")
add_forms(forms, "pres_actv_indc", prefix_e, nil, "es", "est", nil, "estis", nil)
add_forms(forms, "impf_actv_indc", prefix_e, "eram", "erās", "erat", "erāmus", "erātis", "erant")
add_forms(forms, "futr_actv_indc", prefix_e, "erō", {"eris", "ere"}, "erit", "erimus", "eritis", "erunt")
-- Active imperfective subjunctive
add_forms(forms, "pres_actv_subj", prefix_s, "sim", "sīs", "sit", "sīmus", "sītis", "sint")
add_forms(forms, "pres_actv_subj", prefix_s, "siem", "siēs", "siet", "siēmus", "siētis", "sient")
add_forms(forms, "pres_actv_subj", prefix_f, "fuam", "fuās", "fuat", "fuāmus", "fuātis", "fuant")
local noteindex = table_len(data.footnotes) + 1
for _, p in ipairs(persons) do
data.form_footnote_indices[p .. "_pres_actv_subj"] = tostring(noteindex)
end
data.footnotes[noteindex] = "Old Latin or in poetry."
if prefix_s == "ad" then
local noteindex = table_len(data.footnotes) + 1
add_form(forms, "3p_pres_actv_subj", "", "adessint", 2)
data.form_footnote_indices["3p_pres_actv_subj"] = tostring(noteindex)
data.footnotes[noteindex] = "Old Latin."
end
add_forms(forms, "impf_actv_subj", prefix_e, "essem", "essēs", "esset", "essēmus", "essētis", "essent")
add_forms(forms, "impf_actv_subj", prefix_f, "forem", "forēs", "foret", "forēmus", "forētis", "forent")
-- Imperative
add_2_forms(forms, "pres_actv_impr", prefix_e, "es", "este")
add_23_forms(forms, "futr_actv_impr", prefix_e, "estō", "estō", "estōte", nil)
add_form(forms, "3p_futr_actv_impr", prefix_s, "suntō")
-- Infinitives
add_form(forms, "pres_actv_inf", prefix_e, "esse")
add_form(forms, "futr_actv_inf", prefix_f, "fore")
-- Imperfective participles
if prefix == "ab" or prefix == "cōn" or prefix == "prae" or prefix == "præ" then
add_form(forms, "pres_actv_ptc", prefix_s, "sēns")
-- forms["pres_actv_ptc"] = prefix_s .. "sēns"
end
end
irreg_conjugations["volō"] = function(args, data, typeinfo)
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
insert_if_not(categories, "Kata kerja tak teratur bahasa Latin")
insert_if_not(categories, "Kata kerja supletif bahasa Latin")
local prefix = typeinfo.prefix or ""
subtypes.nopass = true
subtypes.noimp = true
subtypes.supfutractvonly = true
make_perf(data, prefix .. "volu")
make_supine(data, typeinfo, prefix .. "volit")
-- Active imperfective indicative
add_forms(forms, "pres_actv_indc", prefix, "volō", "vīs", "vult", "volumus", "vultis", "volunt")
volo_malo_nolo(forms, prefix .. "vol", prefix .. "vel", subtypes)
-- Additional Old Latin forms.
if prefix == "" then
local noteindex = table_len(data.footnotes) + 1
data.footnotes[noteindex] = "Old Latin."
noteindex = tostring(noteindex)
add_forms(forms, "pres_actv_indc", prefix, nil, nil, "volt", nil, "voltis", nil)
data.form_footnote_indices["3s_pres_actv_indc"] = noteindex
data.form_footnote_indices["2p_pres_actv_indc"] = noteindex
-- vol- in the present subjunctive.
add_forms(forms, "pres_actv_subj", prefix .. "vol", "im", "īs", "it", "īmus", "ītis", "int")
for slot in pairs(data.forms) do
if cfind(slot, "pres_actv_subj") then
data.form_footnote_indices[slot] = noteindex
end
end
end
end
local function make_perfect_passive(data)
local forms = data.forms
local ppp = forms["perf_pasv_ptc"]
if type(ppp) ~= "table" then
ppp = {ppp}
end
local ppplinks = {}
for _, pppform in ipairs(ppp) do
insert(ppplinks, make_link(pppform, nil, "term"))
end
local ppplink = concat(ppplinks, " or ")
local sumlink = make_link("sum", nil, "term")
local text_for_slot = {
perf_pasv_indc = "present active indicative",
futp_pasv_indc = "future active indicative",
plup_pasv_indc = "imperfect active indicative",
perf_pasv_subj = "present active subjunctive",
plup_pasv_subj = "imperfect active subjunctive"
}
local passive_prefix, passive_suffix = data.passive_prefix, data.passive_suffix
local prefix_joiner = passive_prefix and passive_prefix:match(" $") and "+ " or ""
local suffix_joiner = passive_suffix and passive_suffix:match("^ ") and " +" or ""
for slot, text in pairs(text_for_slot) do
forms[slot] = (passive_prefix or "") .. prefix_joiner .. ppplink .. " + " ..
text .. " of " .. sumlink .. suffix_joiner .. (passive_suffix or "")
end
ppp = forms["1s_pres_actv_indc"]
if type(ppp) ~= "table" then
ppp = {ppp}
end
end
local function handle_deponent(data, subtypes)
local forms = data.forms
-- Generate a list of form types to remove.
local to_remove = {"pres_pasv_ptc", "futr_pasv_inf"}
if subtypes.depon then
insert(to_remove, "actv")
else
insert(to_remove, "pres_pasv")
insert(to_remove, "impf_pasv")
insert(to_remove, "futr_pasv")
if subtypes.semidepon then
insert(to_remove, "perf_actv")
insert(to_remove, "plup_actv")
insert(to_remove, "futp_actv")
end
end
-- Remove forms.
for slot in pairs(forms) do
if not (
slot == "futr_actv_inf" or
slot == "perp_actv_inf" or
slot == "pres_actv_ptc" or
slot == "futr_actv_ptc" or
slot == "futr_pasv_ptc"
) then
for _, part in ipairs(to_remove) do
if cfind(slot, part) then
forms[slot] = nil
break
end
end
end
end
-- Change passive to active, except for the future passive participle.
local changes = {}
for slot in pairs(forms) do
if cfind(slot, "pasv") and slot ~= "futr_pasv_ptc" then
changes[slot] = slot:gsub("pasv", "actv")
end
end
for old, new in pairs(changes) do
add_form(forms, new, "", forms[old])
forms[old] = nil
end
end
local function add_sync_perf(data, form, suf, note, noteindex)
local forms = data.forms
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local i = 0
while true do
i = i + 1
local stem = formval[i]
if not stem then
break
end
stem = stem:match("^(.*)" .. pattern_escape(suf) .. "$")
-- Can only syncopate "vi", "ve", "vē", or any one of them spelled with a "u" after a vowel.
-- TODO: Syncopate "si", "xi".
if stem then
local new_stem = toNFD(stem)
local vowel, loc, v, ei, diacritic = umatch(new_stem, "(" .. vowel .. "?)" .. LENGTH .. "()([uv])([ei])(" .. LENGTH .. ")$")
if loc and (v == "v" or vowel ~= "") and (ei == "e" or diacritic == "" or cfind(diacritic, BREVE)) then
new_stem = usub(new_stem, 1, loc - 1)
-- Can't be omitted if it's part of the first syllable.
if new_stem:match(vowel) then
i = i + 1
add_form(forms, form, new_stem, suf, i)
data.form_footnote_indices[form] = tostring(noteindex)
data.footnotes[noteindex] = note
end
end
end
end
end
local function has_no_infinitive(forms)
for slot in pairs(forms) do
if cfind(slot, "inf") and not form_is_empty(forms[slot]) then
return false
end
end
return true
end
local function has_no_gerund(forms)
if not form_is_empty(forms["futr_pasv_ptc"]) then
return false
end
for _, case in ipairs(ger_cases) do
if not form_is_empty(forms[case .. "_ger"]) then
return false
end
end
return true
end
local make_conjugation_mt = {}
function make_conjugation_mt:__call(args, data, typeinfo)
if typeinfo.irreg then
self.irreg(args, data, typeinfo)
else
get_regular_stems(args, typeinfo)
self[typeinfo.conj](args, data, typeinfo)
end
local categories, forms, subtypes = data.categories, data.forms, typeinfo.subtypes
if subtypes.nopres or subtypes.perfaspres then
insert_if_not(categories, "Latin verbs with missing present stem")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
end
-- Maybe clear out the supine-derived forms (except maybe for the
-- future active participle). Do this first because some code below
-- looks at the perfect participle to derive other forms.
if subtypes.nosup then
-- Some verbs have no supine forms or forms derived from the supine
insert_if_not(categories, "Latin verbs with missing supine stem")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
forms["futr_actv_inf"] = nil
forms["futr_actv_ptc"] = nil
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
elseif subtypes.nofutractvptc then
-- Some verbs have a missing future active participle
insert_if_not(categories, "Latin verbs with supine stem with missing future active participle")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
forms["futr_actv_ptc"] = nil
forms["perp_actv_inf"] = nil
elseif subtypes.supfutractvonly then
-- Some verbs have no supine forms or forms derived from the supine,
-- except for the future active infinitive/participle
insert_if_not(categories, "Latin verbs with missing supine stem except in the future active participle")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
forms["perf_actv_ptc"] = nil
forms["futp_actv_inf"] = nil
forms["perf_pasv_inf"] = nil
forms["perf_pasv_ptc"] = nil
forms["futr_pasv_inf"] = nil
forms["futp_pasv_inf"] = nil
if subtypes.depon or subtypes.semidepon or subtypes.optsemidepon then
forms["perf_actv_inf"] = nil
end
for _, case in ipairs(sup_cases) do
forms[case .. "_sup"] = nil
end
end
-- Add information for the passive perfective forms
if not (
form_is_empty(forms["perf_pasv_ptc"]) or
subtypes.optsemidepon or
subtypes.impers or
subtypes.passimpers and not (subtypes.depon or subtypes.semidepon or subtypes.optsemidepon) or
subtypes["3only"] or
subtypes.pass3only and not (subtypes.depon or subtypes.semidepon or subtypes.optsemidepon)
) then
make_perfect_passive(data)
end
-- Perfect forms as present tense.
if subtypes.perfaspres then
insert_if_not(categories, "Latin verbs with perfect forms used in the present tense")
-- Remove present active, imperfect active and future active forms and passive forms.
-- Change perfect forms to non-perfect forms.
local new_forms = {}
forms["futr_pasv_inf"] = nil
for slot, form in pairs(forms) do
if not (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
-- If semi-deponent, the perfect passive forms will be converted to perfect active.
if not (cfind(slot, "pasv") and (subtypes.semidepon or subtypes.optsemidepon)) then
slot = slot:gsub("perf", "pres")
:gsub("plup", "impf")
:gsub("futp", "futr")
end
new_forms[slot] = form
end
end
data.forms, forms = new_forms, new_forms
-- No present stem.
elseif subtypes.nopres then
for slot in pairs(forms) do
if (
cfind(slot, "pres") or
cfind(slot, "impf") or
cfind(slot, "futr") and not (cfind(slot, "inf") or cfind(slot, "ptc")) or
slot:match("_ger$")
) then
forms[slot] = nil
end
end
end
-- Types of irregularity related primarily to the active.
-- These could in theory be combined with those related to the passive and imperative,
-- i.e. there's no reason there couldn't be an impersonal deponent verb with no imperatives.
-- Deponent verbs use passive forms with active meaning.
if subtypes.depon then
insert_if_not(categories, "Latin deponent verbs")
handle_deponent(data, subtypes)
-- Semi-deponent verbs use perfective passive forms with active meaning,
-- and have no imperfective passive.
elseif subtypes.semidepon then
insert_if_not(categories, "Kata kerja semideponen bahasa Latin")
handle_deponent(data, subtypes)
-- Optional semi-deponent verbs use perfective passive forms with active
-- meaning, but also have perfect active forms with the same meaning,
-- and have no imperfective passive.
elseif subtypes.optsemidepon then
insert_if_not(categories, "Kata kerja semideponen bahasa Latin")
insert_if_not(categories, "Kata kerja semideponen pilihan bahasa Latin")
handle_deponent(data, subtypes)
elseif subtypes.noperf then
-- Some verbs have no perfect stem (e.g. inalbēscō, -ěre)
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
if not subtypes.depon then
insert_if_not(categories, "Latin verbs with missing perfect stem")
end
-- Remove all active perfect forms (passive perfect forms may
-- still exist as they are formed with the supine stem)
for slot in pairs(forms) do
if cfind(slot, "actv") and (
cfind(slot, "perf") or
cfind(slot, "plup") or
cfind(slot, "futp")
) and slot ~= "futp_actv_inf" then
forms[slot] = nil
end
end
end
-- Handle the removal of any passive forms, including any impersonal/3rd-
-- person-only passives.
-- Third-person only.
if subtypes["3only"] then
insert_if_not(categories, "Kata kerja diri ketiga sahaja bahasa Latin")
for slot in pairs(forms) do
if slot:match("[12][sp]") then
forms[slot] = nil
end
end
-- Impersonal, so remove all non-third-person singular forms.
elseif subtypes.impers then
insert_if_not(categories, "Kata kerja impersonal bahasa Latin")
for slot in pairs(forms) do
if slot:match("[12][sp]") or (
-- Keep third-person plural forms if third-person passive is set.
cfind(slot, "3p") and
not (subtypes.pass3only and cfind(slot, "pasv"))
) then
forms[slot] = nil
end
end
end
-- No passive forms.
if subtypes.nopass then
insert_if_not(categories, "Kata kerja hanya aktif bahasa Latin")
for slot in pairs(forms) do
if cfind(slot, "pasv") then
forms[slot] = nil
end
end
-- Only third person in the passive. For phrasal verbs with a plural
-- complement, also need to erase the 3s forms.
-- FIXME: handling of mp, fp and np needs to be done separately.
elseif subtypes.pass3only then
insert_if_not(categories, "Latin verbs with third-person passive")
local gender = data.gender
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
(gender == "mp" or gender == "fp" or gender == "np") and cfind(slot, "3s")
) then
forms[slot] = nil
end
end
-- Impersonal in the passive, so remove all passive non-third person forms.
elseif subtypes.passimpers then
insert_if_not(categories, "Latin verbs with impersonal passive")
for slot in pairs(forms) do
if cfind(slot, "pasv") and (
slot:match("[12][sp]") or
cfind(slot, "3p")
) then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the imperative
if subtypes.noimp then
-- Some verbs have no imperatives
insert_if_not(categories, "Latin verbs with missing imperative")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
-- Remove all imperative forms
for slot in pairs(forms) do
if cfind(slot, "impr") then
forms[slot] = nil
end
end
end
-- Handle certain irregularities in the future
if subtypes.nofutr then
-- Some verbs (e.g. soleō) have no future
insert_if_not(categories, "Latin verbs with missing future")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
-- Remove all future forms
for slot in pairs(forms) do
if cfind(slot, "fut") then -- handles futr = future and futp = future perfect
forms[slot] = nil
end
end
end
local pres_stem = typeinfo.pres_stem
-- Add the ancient future_passive_participle of certain verbs
-- if pres_stem == "lāb" then
-- forms["futr_pasv_ptc"] = "lābundus"
-- elseif pres_stem == "collāb" then
-- forms["futr_pasv_ptc"] = "collābundus"
-- elseif pres_stem == "illāb" then
-- forms["futr_pasv_ptc"] = "illābundus"
-- elseif pres_stem == "relāb" then
-- forms["futr_pasv_ptc"] = "relābundus"
-- end
-- Add the poetic present passive infinitive forms of certain verbs
if subtypes.p3inf then
local form = "pres_" .. (subtypes.depon and "actv" or "pasv") .. "_inf"
local noteindex = table_len(data.footnotes) + 1
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
for i = 1, table_len(formval) do
insert(formval, usub(formval[i], 1, -2) .. "ier")
end
forms[form] = formval
data.form_footnote_indices[form] = tostring(noteindex)
data.footnotes[noteindex] = "The present passive infinitive in ''-ier'' is a rare poetic form which is attested."
end
--[==[
if subtypes.old2sgimp then
local form = "2s_pres_" .. (subtypes.depon and "actv" or "pasv") .. "_impr"
local formval = forms[form]
if type(formval) ~= "table" then
formval = {formval}
end
local newvals = mw.clone(formval)
end]==]
-- Add the syncopated perfect forms, omitting the separately handled fourth conjugation cases.
if subtypes.poetsyncperf then
local noteindex, note = table_len(data.footnotes) + 1
if pres_stem and pres_stem:match("nōsc$") then
note = 'The verb "nōscō" and its compounds frequently drop the syllables "vi" and "ve" from their perfect, pluperfect and future perfect conjugations.'
else
note = "At least one rare poetic syncopated perfect form is attested."
end
-- infinitive
add_sync_perf(data, "perf_actv_inf", "sse", note, noteindex)
-- perfect actives
add_sync_perf(data, "2s_perf_actv_indc", "stī", note, noteindex)
add_sync_perf(data, "3s_perf_actv_indc", "t", note, noteindex)
add_sync_perf(data, "1p_perf_actv_indc", "mus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_indc", "stis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_indc", "runt", note, noteindex)
-- pluperfect actives
add_sync_perf(data, "1s_plup_actv_indc", "ram", note, noteindex)
add_sync_perf(data, "2s_plup_actv_indc", "rās", note, noteindex)
add_sync_perf(data, "3s_plup_actv_indc", "rat", note, noteindex)
add_sync_perf(data, "1p_plup_actv_indc", "rāmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_indc", "rātis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_indc", "rant", note, noteindex)
-- future perfect actives
add_sync_perf(data, "1s_futp_actv_indc", "rō", note, noteindex)
add_sync_perf(data, "2s_futp_actv_indc", "ris", note, noteindex)
add_sync_perf(data, "3s_futp_actv_indc", "rit", note, noteindex)
add_sync_perf(data, "1p_futp_actv_indc", "rimus", note, noteindex)
add_sync_perf(data, "2p_futp_actv_indc", "ritis", note, noteindex)
add_sync_perf(data, "3p_futp_actv_indc", "rint", note, noteindex)
-- perfect subjunctives
add_sync_perf(data, "1s_perf_actv_subj", "rim", note, noteindex)
add_sync_perf(data, "2s_perf_actv_subj", "rīs", note, noteindex)
add_sync_perf(data, "3s_perf_actv_subj", "rit", note, noteindex)
add_sync_perf(data, "1p_perf_actv_subj", "rīmus", note, noteindex)
add_sync_perf(data, "2p_perf_actv_subj", "rītis", note, noteindex)
add_sync_perf(data, "3p_perf_actv_subj", "rint", note, noteindex)
-- pluperfect subjunctives
add_sync_perf(data, "1s_plup_actv_subj", "ssem", note, noteindex)
add_sync_perf(data, "2s_plup_actv_subj", "ssēs", note, noteindex)
add_sync_perf(data, "3s_plup_actv_subj", "sset", note, noteindex)
add_sync_perf(data, "1p_plup_actv_subj", "ssēmus", note, noteindex)
add_sync_perf(data, "2p_plup_actv_subj", "ssētis", note, noteindex)
add_sync_perf(data, "3p_plup_actv_subj", "ssent", note, noteindex)
end
if subtypes.syncfutractvptc then
-- TODO
end
-- Add category for sigmatic forms
if subtypes.sigm then
insert_if_not(categories, "Latin verbs with sigmatic forms")
-- Add subcategory for (very rare) passive sigmatic forms
if subtypes.sigmpasv then
insert_if_not(categories, "Latin verbs with passive sigmatic forms")
end
end
if subtypes.noinf then
-- Some verbs (e.g. inquam) have no infinitives
for slot in pairs(forms) do
if cfind(slot, "inf") then
forms[slot] = nil
end
end
end
if has_no_infinitive(forms) then
subtypes.noinf = true
insert_if_not(categories, "Latin verbs with missing infinitive")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
end
if subtypes.noger then
-- Some verbs (e.g. libet) have no gerund
forms["futr_pasv_ptc"] = nil
for _, case in ipairs(ger_cases) do
forms[case .. "_ger"] = nil
end
end
-- Catch verbs which don't have .noger explicitly specified.
if has_no_gerund(forms) then
subtypes.noger = true
insert_if_not(categories, "Latin verbs with missing gerund")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
end
if subtypes.imponly then
-- Some verbs only have imperatives
insert_if_not(categories, "Latin imperative-only verbs")
insert_if_not(categories, "Kata kerja defektif bahasa Latin")
-- Remove all non-imperative forms
for slot in pairs(forms) do
if not cfind(slot, "impr") then
forms[slot] = nil
end
end
end
end
setmetatable(make_conjugation, make_conjugation_mt)
-- Functions for generating the inflection table
-- Convert FORM (one or more forms) to a string of links. If the form is empty
-- (see form_is_empty), the return value will be "—".
local function show_form(formval, accel)
if not formval then
return "—"
elseif type(formval) ~= "table" then
formval = {formval}
elseif table_len(formval) == 0 then
return "—"
end
for slot, form in ipairs(formval) do
if form_is_empty(form) then
form = "—"
elseif form:match("%[%[.-]]") then
-- Don't put accelerators on forms already containing links such as
-- the perfect passive infinitive and future active infinitive, or
-- the participles wrongly get tagged as infinitives as well as
-- participles.
form = make_link(form)
else
form = make_link(form, nil, nil, accel)
end
formval[slot] = form
end
return concat(formval, ",<br> ")
end
local parts_to_tags = {
['1s'] = {'1', 's'},
['2s'] = {'2', 's'},
['3s'] = {'3', 's'},
['1p'] = {'1', 'p'},
['2p'] = {'2', 'p'},
['3p'] = {'3', 'p'},
['actv'] = {'act'},
['pasv'] = {'pass'},
['pres'] = {'pres'},
['impf'] = {'impf'},
['futr'] = {'fut'},
['perf'] = {'perf'},
['plup'] = {'plup'},
['futp'] = {'futp'},
['perp'] = {'perf', 'potn'},
['sigm'] = {'sigm'},
['sigf'] = {'sigm', 'fut'},
['siga'] = {'sigm', 'aor'},
['indc'] = {'ind'},
['subj'] = {'sub'},
['impr'] = {'imp'},
['inf'] = {'inf'},
['ptc'] = {'part'},
['ger'] = {'ger'},
['sup'] = {'sup'},
['nom'] = {'nom'},
['gen'] = {'gen'},
['dat'] = {'dat'},
['acc'] = {'acc'},
['abl'] = {'abl'},
}
-- Call show_form() the forms in each non-generic slot (where a
-- generic slot is something like pres_actv_indc that covers a whole
-- row of slots), converting the forms to a string consisting of
-- comma-separated links with accelerators in them.
local function convert_forms_into_links(data)
local accel_lemma, forms = data.actual_lemma[1], data.forms
for slot in iter_slots(false, false) do
local slot_parts = split(slot, "_")
local tags = {}
for _, part in ipairs(slot_parts) do
for _, tag in ipairs(parts_to_tags[part]) do
insert(tags, tag)
end
end
-- put the case first for verbal nouns
local accel = {form = concat(tags, "|"), lemma = accel_lemma}
forms[slot] = show_form(forms[slot], accel)
end
end
function export.get_valid_forms(raw_forms)
local valid_forms = {}
if raw_forms then
if type(raw_forms) ~= "table" then
raw_forms = {raw_forms}
end
for _, subform in ipairs(raw_forms) do
if not form_is_empty(subform) then
insert(valid_forms, subform)
end
end
end
return valid_forms
end
function export.get_lemma_forms(data, do_linked)
local linked_prefix, forms = do_linked and "linked_" or "", data.forms
for _, slot in ipairs(potential_lemma_slots) do
local lemma_forms = export.get_valid_forms(forms[linked_prefix .. slot])
if table_len(lemma_forms) > 0 then
return lemma_forms
end
end
return nil
end
local function get_displayable_lemma(lemma_forms)
if not lemma_forms then
return "—"
end
local lemma_links = {}
for _, subform in ipairs(lemma_forms) do
insert(lemma_links, make_link(nil, subform, "term"))
end
return concat(lemma_links, ", ")
end
local tenses_display = {
["pres"] = "present",
["impf"] = "imperfect",
["futr"] = "future",
["perf"] = "perfect",
["plup"] = "pluperfect",
["futp"] = "future perfect",
["perp"] = "perfect potential",
["sigf"] = "sigmatic future",
["siga"] = "sigmatic aorist"
}
local voices_display = {
["actv"] = "active",
["pasv"] = "passive",
}
local moods_display = {
["indc"] = "indicative",
["subj"] = "subjunctive",
["impr"] = "imperative",
}
--[[
local nonfins = {
["inf"] = "infinitives",
["ptc"] = "participles",
}
--]]
--[[
local verbalnouns = {
["ger"] = "gerund",
["sup"] = "supine",
}
--]]
--[[
local cases = {
["nom"] = "nominative",
["gen"] = "genitive",
["dat"] = "dative",
["acc"] = "accusative",
["abl"] = "ablative",
}
--]]
local function make_row(data, prefixes, headspan, cellspan, rowslot, rowname, class, fn)
local row = {}
if rowname then
insert(row, ('\n! class="%s"%s | %s%s'):format(class, headspan == 1 and "" or (' colspan="%d"'):format(headspan), rowname, fn or ""))
end
local has_row, forms = false, data.forms
if not form_is_empty(forms[rowslot]) then
if type(forms[rowslot]) == "table" then
if table_len(forms[rowslot]) > 1 then
error("Row slot " .. rowslot .. " cannot have more than one value.")
end
forms[rowslot] = forms[rowslot][1]
end
insert(row, '\n! colspan="12" class="roa-compound-row" |' .. forms[rowslot])
has_row = true
else
for _, prefix in ipairs(prefixes) do
local slot = prefix .. (rowslot and "_" .. rowslot or "")
insert(row, ('\n| colspan="%d" | '):format(cellspan) .. forms[slot] .. (
data.form_footnote_indices[slot] == nil and "" or
'<sup class="roa-red-superscript">' .. data.form_footnote_indices[slot] .. "</sup>"
))
if not form_is_empty(forms[slot]) then
has_row = true
end
end
end
return has_row and concat(row) or false
end
local function make_group(data, _tenses, voice, mood, class)
local group = {}
for _, tense in ipairs(_tenses) do
local fn = ""
if tense == "sigf" or tense == "siga" then
fn = data.form_footnote_indices["sigm"]
fn = fn and ('<sup class="roa-red-superscript">' .. fn .. "</sup>") or ""
end
local row = make_row(data, persons, 1, 2, tense .. "_" .. voice .. "_" .. mood, tenses_display[tense], class, fn)
if row then
insert(group, row)
end
end
return #group > 0 and ('\n|-\n! rowspan="' .. tostring(#group) .. '" class="' .. class .. '" | ' .. voices_display[voice] .. concat(group, "\n|-")) or false
end
local function make_section(data, mood, _tenses)
local section, name = {}, moods_display[mood]
local class = "roa-" .. name .. "-left-rail"
for _, voice in ipairs(voices) do
local group = make_group(data, _tenses, voice, mood, class)
if group then
insert(section, group)
end
end
if #section == 0 then
return ""
end
return (([=[
|-
! colspan="2" rowspan="2" class="%CLASS" | %NAME
! colspan="6" class="%CLASS" | ''singular''
! colspan="6" class="%CLASS" | ''plural''
|-
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[first person|first]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[second person|second]]
! colspan="2" class="%CLASS" style="width:12.5%;" | [[third person|third]]]=]):gsub("%%%u+", function(m)
return m == "%NAME" and name or m == "%CLASS" and class or m
end)) .. concat(section)
end
local function make_indc_rows(data)
return make_section(data, "indc", indc_tenses)
end
local function make_subj_rows(data)
return make_section(data, "subj", subj_tenses)
end
local function make_impr_rows(data)
return make_section(data, "impr", impr_tenses)
end
local function get_nonfin_cells(t)
local cells = {}
for _, f in ipairs{"inf", "ptc"} do
for _, v in ipairs(voices) do
insert(cells, t .. "_" .. v .. "_" .. f)
end
end
return cells
end
local function make_nonfin_rows(data)
local nonfin = {}
for _, t in ipairs(nonfin_tenses) do
local row = make_row(data, get_nonfin_cells(t), 2, 3, nil, tenses_display[t], "roa-nonfinite-header")
if row then
insert(nonfin, row)
end
end
if #nonfin == 0 then
return ""
end
return [=[
|-
! colspan="2" rowspan="2" class="roa-nonfinite-header" | non-finite forms
! colspan="6" class="roa-nonfinite-header" | infinitive
! colspan="6" class="roa-nonfinite-header" | participle
|-
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | active
! colspan="3" class="roa-nonfinite-header" style="width:18.75%;" | passive
|-]=] .. concat(nonfin, "\n|-")
end
local function make_vn_rows(data)
local vn = make_row(data, {"gen_ger", "dat_ger", "acc_ger", "abl_ger", "acc_sup", "abl_sup"}, nil, 2, nil, nil, "roa-nonfinite-header")
if not vn then
return ""
end
return [=[
|-
! colspan="2" rowspan="3" class="roa-nonfinite-header" | verbal nouns
! colspan="8" class="roa-nonfinite-header" | gerund
! colspan="4" class="roa-nonfinite-header" | supine
|-
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | genitive
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | dative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | accusative
! colspan="2" class="roa-nonfinite-header" style="width:12.5%;" | ablative
|-]=] .. vn
end
local function make_footnotes(data)
local tbl, i = {}, 0
for k, v in pairs(data.footnotes) do
i = i + 1
tbl[i] = '<sup class="roa-red-superscript">' .. tostring(k) .. '</sup>' .. v .. '<br>'
end
return concat(tbl)
end
-- Make the table
local function make_table(data)
data.actual_lemma = export.get_lemma_forms(data)
convert_forms_into_links(data)
local title = data.title
return require("Module:TemplateStyles")("Module:roa-verb/style.css") .. [=[
<div class="NavFrame">
<div class="NavHead"> Conjugation of ]=] .. get_displayable_lemma(data.actual_lemma) .. (table_len(title) > 0 and " (" .. concat(title, ", ") .. ")" or "") .. [=[</div>
<div class="NavContent">
{| class="roa-inflection-table" data-toggle-category="inflection"
]=] .. make_indc_rows(data) .. make_subj_rows(data) .. make_impr_rows(data) .. make_nonfin_rows(data) .. make_vn_rows(data) .. [=[
|}</div></div>]=].. make_footnotes(data)
end
local function checkexist(data)
if NAMESPACE ~= "" then
return
end
local outerbreak = false
local categories = data.categories
for _, conjugation in pairs(data.forms) do
if conjugation then
if type(conjugation) ~= "table" then
conjugation = {conjugation}
end
for _, conj in ipairs(conjugation) do
if not cfind(conj, " ") and not cfind(conj, "[") then
local physical_page = lang:logicalToPhysical(lang:stripDiacritics(conj))
local t = mw.title.new(physical_page)
if t and not t:getContent() then
insert_if_not(categories, "Latin verbs with red links in their inflection tables")
outerbreak = true
break
end
end
end
end
if outerbreak then
break
end
end
end
-- functions for creating external search hyperlinks
local function cleanup(x)
x:gsub("[[%]]", "")
:gsub(" ", "+")
return toNFC((ugsub(toNFD(x), "[^%w]+", "")))
end
local function flatten_values(t)
t = flatten(t)
local i = 1
while true do
local v = t[i]
if v == nil then
return t
elseif cfind(v, "<") then
remove(t, i)
else
t[i] = cleanup(v)
i = i + 1
end
end
end
local function link_google_books(verb, forms, domain)
local function partition_XS_into_N(XS, N)
local count = 0
local mensae = {}
for _, v in pairs(XS) do
if count % N == 0 then
mensae[#mensae+1] = {}
end
count = count + 1
mensae[#mensae][#(mensae[#mensae])+1] = v
end
return mensae
end
local function forms_N_to_link(fs, N, args, site)
return '[https://www.google.com/search?'..args..'&q='..site..'+%22'.. concat(fs, "%22+OR+%22") ..'%22 '..N..']'
end
local function make_links_txt(fs, N, site)
local args = site == "Books" and "tbm=bks&lr=lang_la" or ""
local links = {}
for k,v in pairs(partition_XS_into_N(fs, N)) do
links[#links+1] = forms_N_to_link(v,k,args,site=="Books" and "" or site)
end
return concat(links, ' - ')
end
return "Google "..domain.." forms of "..verb.." : "..make_links_txt(forms, 30, domain)
end
-- The main new entry point.
function export.show(frame)
local parent_args = frame:getParent().args
local data, typeinfo = export.make_data(parent_args)
if type(data) == "string" then -- json=1 specified
return data
end
local domain = frame:getParent().args['search']
-- Test code to compare existing module to new one.
if test_new_la_verb_module then
local m_new_la_verb = require("Module:User:Benwing2/la-verb")
local miscdata = {
title = data.title,
categories = data.categories,
}
local new_parent_args = frame:getParent().args
local newdata = m_new_la_verb.make_data(new_parent_args)
local newmiscdata = {
title = newdata.title,
categories = newdata.categories,
}
local all_verb_props = {"forms", "form_footnote_indices", "footnotes", "miscdata"}
local difconj = false
for _, prop in ipairs(all_verb_props) do
local table = prop == "miscdata" and miscdata or data[prop]
local newtable = prop == "miscdata" and newmiscdata or newdata[prop]
for key, val in pairs(table) do
local newval = newtable[key]
if not forms_equal(val, newval) then
-- Uncomment this to display the particular key and
-- differing forms.
-- error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
if difconj then
break
end
-- Do the comparison the other way as well in case of extra keys
-- in the new table.
for key, newval in pairs(newtable) do
local val = table[key]
if not forms_equal(val, newval) then
-- Uncomment this to display the particular key and
-- differing forms.
-- error(key .. " " .. (val and concat_vals(val) or "nil") .. " || " .. (newval and concat_vals(newval) or "nil"))
difconj = true
break
end
end
if difconj then
break
end
end
track(difconj and "different-conj" or "same-conj")
end
if typeinfo.subtypes.suffix then
data.categories = {}
end
-- Check if the links to the verb forms exist
-- Has to happen after other categories are removed for suffixes
checkexist(data)
if domain == nil then
return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end
local verb = data['forms']['1s_pres_actv_indc'] ~= nil and ('[[' .. toNFC((ugsub(toNFD(data['forms']['1s_pres_actv_indc']), '[^%w]+', ""))) .. '|' .. data['forms']['1s_pres_actv_indc'] .. ']]') or 'verb'
return link_google_books(verb, flatten_values(data['forms']), domain)
end
return export
gv6h8j2xzhf12bdi5r779g7954wjck0
Modul:la-utilities
828
16911
344382
117688
2026-05-25T23:21:22Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/84555914|84555914]])
344382
Scribunto
text/plain
local export = {}
local debug_track_module = "Module:debug/track"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local gsub = string.gsub
local ipairs = ipairs
local join -- defined below
local match = string.match
local normalize_form -- defined below
local pairs = pairs
local remove = table.remove
local require = require
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD
local type = type
local u = mw.ustring.char
local umatch = mw.ustring.match
local MACRON = u(0x304)
local VOWEL = "[aæeioœuyAÆEIOŒUY]"
local function contains(...)
contains = require(table_module).contains
return contains(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function decode_entities(...)
decode_entities = require(string_utilities_module).decode_entities
return decode_entities(...)
end
local function deep_equals(...)
deep_equals = require(table_module).deepEquals
return deep_equals(...)
end
local function insert_if_not(...)
insert_if_not = require(table_module).insertIfNot
return insert_if_not(...)
end
local function table_len(...)
table_len = require(table_module).length
return table_len(...)
end
local function trim(...)
trim = require(string_utilities_module).trim
return trim(...)
end
local function ugsub(...)
ugsub = require(string_utilities_module).gsub
return ugsub(...)
end
export.cases = {
["nom"] = "nominative",
["gen"] = "genitive",
["dat"] = "dative",
["acc"] = "accusative",
["abl"] = "ablative",
["voc"] = "vocative",
["loc"] = "locative",
}
local cons_to_vowel = {
["j"] = "i", ["J"] = "I",
["v"] = "u", ["V"] = "U",
}
local function link_if_unlinked(text)
return match(text, "%[%[.-]]") and text or ugsub(text, "^(%s*)(.-)(%s*)$", "%1[[%2]]%3")
end
function export.join(a, b)
a, b = toNFD(a), toNFD(b)
-- If the first part ends in "j" or "v", convert it to "i" or "u" unless
-- the second part begins with a vowel.
if not umatch(b, "^" .. VOWEL) then
a = gsub(a, "[jvJV]$", cons_to_vowel)
end
-- If there is a space between the two forms, link both parts separately.
if umatch(a, "%s$") or umatch(b, "^%s") then
a, b = link_if_unlinked(a), link_if_unlinked(b)
end
return toNFC(a .. b)
end
join = export.join
local function normalized_form_is_empty(form)
local cancelled_forms = require(table_module).listToSet{"", "-", "–", "—", "―", "⸺", "⸻"}
function normalized_form_is_empty(form)
return not (form and not cancelled_forms[form])
end
return normalized_form_is_empty(form)
end
function export.normalize_form(form)
if form == nil then
return nil
elseif normalized_form_is_empty(form) then
return "-"
end
local form_type = type(form)
if form_type ~= "table" then
if form_type == "string" then
form = trim(decode_entities(form))
end
return normalized_form_is_empty(form) and "-" or form
end
local i, subform = 1, form[1]
while subform ~= nil do
subform = normalize_form(subform)
if normalized_form_is_empty(subform) then
remove(form, i)
else
-- Check against all earlier subforms, in case it's a duplicate.
-- Use a loop rather than a table lookup, as it's more efficient
-- when the number of subforms is less than 5, which is almost
-- always the case.
local duplicate = false
for j = 1, i - 1 do
if deep_equals(subform, form[j]) then
duplicate = true
remove(form, i)
break
end
end
if not duplicate then
form[i] = subform
i = i + 1
end
end
subform = form[i]
end
local form_len = i - 1
if form_len == 0 then
return "-"
elseif form_len == 1 then
return form[1]
end
return form
end
normalize_form = export.normalize_form
function export.form_is_empty(form)
return normalized_form_is_empty(normalize_form(form))
end
-- For a given form, we allow either strings (a single form) or lists of forms,
-- and treat strings equivalent to one-element lists.
function export.forms_equal(form1, form2)
return deep_equals(normalize_form(form1), normalize_form(form2))
end
function export.form_contains(form, str)
form = normalize_form(form)
if normalized_form_is_empty(form) then
return false
end
str = normalize_form(str)
if type(form) ~= "table" then
return deep_equals(form, str)
end
return contains(form, str)
end
-- Add a value to a given form key, e.g. "1s_pres_actv_indc". If the value is
-- already present in the key, it won't be added again.
--
-- The value is formed by concatenating `stem` and `suf`. `suf` can be a list,
-- in which case `stem` will be concatenated in turn to each value in the list
-- and all the resulting forms added to the key.
--
-- `pos` is the position to insert the form(s) at; default is at the end. To
-- insert at the beginning, specify 1 for `pos`.
do
local options = {}
local function _add_form(forms, slot, stem, suf, pos)
local curr_form = normalize_form(forms[slot])
local new_form = normalize_form(suf == nil and stem or join(stem, suf))
if normalized_form_is_empty(curr_form) then
forms[slot] = new_form
return
elseif deep_equals(curr_form, new_form) then
forms[slot] = curr_form
return pos
elseif type(curr_form) ~= "table" then
curr_form = {curr_form}
end
options.pos = pos
local success = insert_if_not(curr_form, new_form, options)
forms[slot] = curr_form
return pos ~= nil and success and pos + 1 or pos
end
local function add_stem(forms, slot, stem, suf, pos)
if suf and type(suf) == "table" then
for _, s in ipairs(suf) do
pos = _add_form(forms, slot, stem, s, pos)
end
return pos
else
return _add_form(forms, slot, stem, suf, pos)
end
end
local function add_slot(forms, slot, stem, suf, pos)
-- Bound `pos` between 1 and the current number of forms + 1.
if pos then
local form = forms[slot]
if not form then
pos = nil
elseif pos <= 1 then
pos = 1
elseif not (type(form) == "table" and pos <= table_len(form)) then
pos = nil
end
end
if type(stem) == "table" then
for _, s in ipairs(stem) do
pos = add_stem(forms, slot, s, suf, pos)
end
else
add_stem(forms, slot, stem, suf, pos)
end
end
--[==[
Adds one or more forms to `forms`, which is a table of inflections:
* `slot` is the specifier for the form (e.g. "gen_sg"). This does not need to exist before this function is called.
* `stem` is the stem for the form. If `suf` is supplied, `stem` and `suf` will be combined using `exprt.join()` (which accounts for i/j and u/v alternation), and added to the relevant slot(s). If `suf` is not supplied, `stem` will be taken as the form.
* Any or all of `slot`, `stem` and `suf` can optionally be given as a list, in which case all stem/suffix combinations will be generated, which will be added to each of the listed slots. This is useful when adding multiple forms to the same slot, or when the forms are identical between slots (or both).
* If `pos` is supplied, the form(s) will be added to at the specified position in each slot specified.
Note that this function automatically handles duplicates, forms as strings, forms as lists, and cancelled forms (specified with "-").]==]
function export.add_form(forms, slot, stem, suf, pos)
if type(slot) == "table" then
for _, s in ipairs(slot) do
pos = add_slot(forms, s, stem, suf, pos)
end
else
add_slot(forms, slot, stem, suf, pos)
end
end
end
do
local check_keytypes
local function check_exceptions(slot, forms, keytypes, exceptions)
for _, keytype in ipairs(exceptions) do
if match(slot, keytype) then
return true
end
end
if keytypes then
check_keytypes(slot, forms, keytypes)
end
end
function check_keytypes(slot, forms, keytypes, exceptions)
for _, keytype in ipairs(keytypes) do
if match(slot, keytype) and not (exceptions and check_exceptions(slot, forms, nil, exceptions)) then
forms[slot] = nil
return
end
end
end
-- Remove all forms with a key matching any of the keys in the list
-- `keytypes`, unless they match any keytypes listed in `exceptions`.
function export.remove_forms(forms, keytypes, exceptions)
-- Check the shorter list first.
local func = (exceptions == nil or #exceptions >= #keytypes) and check_keytypes or check_exceptions
for slot in pairs(forms) do
func(slot, forms, keytypes, exceptions)
end
end
end
local patterns = {
{"[mM]a", "%0t"},
{"e", ""},
{"([aoAO])([lr])", "%1" .. MACRON .. "%2"},
{"[eE]l", "%0l"},
{"([mM])en", "%1in"},
{"([tT]ūd)ō", "%1in"},
{"([gG])ō", "%1in"},
{"[ōŌ]", "%1n"},
{"er", "r"},
{"[ēi]s", ""},
{"([āēīōūȳĀĒĪŌŪȲ]n)s", function(v)
return (gsub(toNFD(v), MACRON, "") .. "t")
end},
{"([cC])eps", "%1ipit"},
{"([bp])s", "%1"},
{"us", "or"},
{"s", "t"},
{"ex", "ic"},
{"x", "c"},
}
function export.make_stem2(stem)
local n
for _, pattern in ipairs(patterns) do
local key = pattern[1]
stem, n = ugsub(stem, key .. "$", pattern[2])
if n > 0 then
debug_track("la-utilities/" .. key)
return toNFC(stem)
end
end
debug_track("la-utilities")
return stem
end
return export
mg9kh10v0xgcynliifkmqapr41d5eg4
ilmu alat
0
16936
344400
333965
2026-05-26T04:06:37Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344400
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# {{lb|ms|pengajian Islam}} [[ilmu|Ilmu-ilmu]] asas dalam [[pengajian Islam]] seperti asas [[bahasa Arab]], [[mantik]], [[usul fiqh]] dan sebagainya.
#* {{quote-web|ms|work=Berita Harian|title='Empat tahun tidak cukup jadi alim'|url=https://www.bharian.com.my/rencana/agama/2018/12/514305/empat-tahun-tidak-cukup-jadi-alim|date=2018-12-30|passage=Pendakwah muda, Dr Muhammad Ayman al-Akiti, berkata dalam bidang agama, ulama terdahulu sudah meletakkan syarat untuk menjadi ustaz atau ilmuwan perlu terlebih dulu menguasai '''ilmu alat''' seperti bahasa Arab yang merangkumi nahu, sorof dan sastera balaghah yang menjadi kunci untuk memahami ilmu agama yang lain.}}
#* {{quote-web|ms|work=Pejabat Mufti Wilayah Persekutuan|title=Irsyad Al-Fatwa #252: Hukum Mempelajar Ilmu Mantiq|url=https://muftiwp.gov.my/artikel/irsyad-fatwa/irsyad-fatwa-umum/2664-irsyad-al-fatwa-252-hukum-mempelajar-ilmu-mantiq|date=2018-10-13|quote=Ilmu mantiq merupakan salah satu '''ilmu alat''' yang amat penting bagi memahami ibarat-ibarat kitab-kitab turath, disamping nahu, sorof, balaghah dan lain-lain.}}
===Etimologi===
Daripada {{compound|ms|ilmu|alat}}.
===Sebutan===
* {{dewan|il|mu|a|lat}}
===Tulisan Jawi===
{{ARchar|[[علمو الت]]}}
===Tesarurus===
====Sinonim====
* [[ilmu mabadi]]
===Rujukan===
* {{R:KDP}}
===Pautan luar===
* {{R:PRPM}}
rb0bgnpamq2ouvrffdr7uj7anns9t3g
nyahkotak
0
16957
344406
335640
2026-05-26T04:07:19Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344406
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata kerja===
{{ms-kk}}
# Membuka kotak berisi suatu barangan baharu di hadapan kamera dengan tujuan untuk melakukan penilaian terhadap barangan yang dibuka.
:# {{quote-web|ms|title=Vocket Review: Nyahkotak realme C12, Telefon Pintar Kelas Permulaan Untuk Semua|url=https://www.thevocket.com/vocket-review-nyahkotak-realme-c12-telefon-pintar-kelas-permulaan-untuk-semua/|work=The Vocket|date=2020-08-20|passage=Aiman '''nyahkotak''' satu persatu apa yang terkandung dalam kotak yang diberi dan apa yang mengejutkan kami adalah peranti ini mempunyai Tri-Kamera belakang dan juga rekaannya yang ‘simple’ serta bateri yang berkapisiti besar iaitu 6000 mAh ‘Mega Battery’.}}
:# {{quote-web|ms|title=Video nyahkotak PS5 telah mula dimuat naik|url=https://www.esportsasia.com/video-nyahkotak-ps5-telah-mula-dimuat-naik|work=Esports Asia|date=2020-10-28|quote=Nampaknya sekatan untuk muat naik video dan penulisan tentang aktiviti '''nyahkotak''' PlayStation 5 (PS5) telah ditamatkan semalam. Ini memberi peluang kepada kita semua untuk melihat pendapat-pendapat daripada beberapa pempengaruh dan syarikat media yang menerima unit ulasan konsol tersebut.}}
===Etimologi===
Daripada {{prefix|ms|nyah|kotak}}. {{calque|ms|en|unboxing}}.
===Sebutan===
* {{dewan|nyah|ko|tak}}
===Tulisan Jawi===
{{ARchar|[[ڽهکوتق]]}}
===Pautan luar===
* {{R:PRPM}}
m3yvh547l41utaxdefinx4uqvk1hybh
dua darjat
0
16958
344402
335436
2026-05-26T04:06:53Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344402
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata sifat===
{{ms-ks}}
# Layanan atau peraturan yang tidak adil atau [[sama rata]] antara golongan kelas atasan dengan kelas bawahan.
:# {{quote-web|ms|title=Daim: 'Semua orang pening' SOP berubah-ubah|work=Malaysiakini|date=2021-02-15|url=https://www.malaysiakini.com/news/562974|passage="Apa yang rakyat nampak ialah penguatkuasaan undang undang '''dua darjat''' – lain untuk rakyat lain untuk orang berkedudukan tinggi,” katanya.}}
:# {{quote-web|ms|title=SOP 'dua darjat' sukarkan usaha profesional kesihatan - MHC|work=Astro Awani|date=2021-01-09|url=https://www.astroawani.com/berita-malaysia/sop-dua-darjat-sukarkan-usaha-profesional-kesihatan-mhc-282097|quote=“SOP yang tidak berpandukan sains dan bukti akan menghakis keyakinan terhadap SOP. Penguatkuasaan SOP '''dua darjat''' akan menyebabkan kepercayaan rakyat terhadap ahli politik semakin merosot.}}
===Etimologi===
Daripada {{compound|ms|dua|darjat}}. Asal daripada judul filem [[w:Antara Dua Darjat|''Antara Dua Darjat'']] (1960) oleh [[w:P.Ramlee|P. Ramlee]].
===Sebutan===
* {{dewan|dua|dar|jat}}
===Tulisan Jawi===
{{ARchar|[[دوا درجت]]}}
===Pautan luar===
* {{R:PRPM}}
0yj279nr67cgz3fzplrnij90mibhwp7
ampus
0
16976
344404
308168
2026-05-26T04:07:06Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344404
wikitext
text/x-wiki
==Bahasa Iban==
===Kata nama===
{{inti|iba|kata nama}}
# [[asma]]
#: {{cp|iba|Selumbong bisi penyakit '''ampus''' ari iya agi mit suba.|Selumbong mempunyai penyakit '''asma''' sejak dari dia kecil lagi.}}
===Sebutan===
* {{audio|iba|LL-Q33424 (iba)-Song GK-ampus.wav}}
==Bahasa Melayu Brunei==
===Kata nama===
{{head|kxd|kata nama}}
# [[asma]], [[sesak nafas]]
:# {{quote-web|kxd|nodate=yes|url=http://www.moh.gov.bn/SiteCollectionDocuments/Occupational%20Health%20Division/work%20series/form02-07-51.pdf|title=Penyakit Ampus (Asma) dan Kerja Anda|work=Kementerian Kesihatan Brunei|passage=Jika penyakit '''ampus''' bertambah buruk, doktor anda mungkin menyarankan anda untuk anda dipindahkan kerja kebahagian lain dan didalam kes teruk, menyarankan anda untuk mencari pekerjaan yang lain untuk memelihara kesihatan anda.}}
===Sebutan===
* {{penyempangan|kxd|am|pus}}
===Tulisan Jawi===
{{ARchar|[[امڤوس]]}}
{{C|kxd|Patologi}}
==Bahasa Melayu Sabah==
===Kata nama===
{{head|msi|kata nama}}
# [[asma]], [[sesak nafas]]
:# {{ux|msi|'''Ampus''' si Manan masa main bubut-bubut tadi.|Maman sesak nafas semasa main kejar-kejar tadi.}}
===Sebutan===
* {{penyempangan|msi|am|pus}}
{{C|msi|Patologi}}
ga3sg0te32pllpsco8sx8x9wl0u8r5w
si mati
0
16980
344409
335134
2026-05-26T04:08:19Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344409
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn|si mati}}
# {{lb|ms|undang-undang}} Orang yang sudah [[meninggal dunia]] atau [[mati]].
#: {{quote-book|ms|title=The Malayan Law Journal|year=2003|publisher=Malaya Publishing House Limited|author=Bashir Ahmad Mallal|page=403|text=Jarak di antara OKT dan '''si mati''' lebih kurang 10 kaki. Dari jarak itu tembakan kedua dibuat.}}
#: {{quote-web|ms|title=Lelaki mati dalam kereta dipercayai akibat terhidu asap – Polis|work=Utusan Malaysia|date=2021-02-22|url=https://www.utusan.com.my/nasional/2021/02/lelaki-mati-dalam-kereta-dipercayai-akibat-terhidu-asap-polis/|passage=“Mereka mengambil ‘swab’ peluh (DNA), pelitup muka, botol air minuman, penyala api dan satu bekas mengandungi bahan bakar disyaki arang yang digunakan '''si mati''' dalam kejadian ini untuk siasatan lanjut,” katanya kepada pemberita di sini hari ini.}}
===Etimologi===
Daripada {{compound|ms|si|mati}}.
===Sebutan===
* {{dewan|si|ma|ti}}
===Tulisan Jawi===
{{ARchar|[[سي ماتي]]}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
[[Kategori:ms:Orang]]
07ux9ishoxgpak5w0jf1tc48xx6pkdl
rasi
0
17007
344394
333534
2026-05-26T04:04:42Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344394
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# {{lb|ms|klasik|astrologi}} [[buruj]] (kumpulan bintang yang dikatakan menyerupai objek)
:# {{quote-web|ms|url=http://klikweb.dbp.my/?p=4641|title=Muncul-Lesapnya Konsep dan Istilah Asli Sains dan Matematik dalam Bahasa Melayu Sebelum Abad Kedua Puluh Masihi|date=2013-03-30|work=Dewan Bahasa dan Pustaka|quote=Objek-objek di alam semesta ini, mengikut teori kini, terdiri daripada 88 buah kumpulan bintang (diistiharkan oleh ''International Astronomical Union'', sejak 1928) yang setiap kumpulan bintang ini diistilahkan sebagai '''rasi''' (dalam bahasa Melayu pra-Islam mungkin sekali sejak abad ke-7 M) atau buruj (bahasa Melayu klasik, daripada bahasa Arab, sejak abad ke-12 M mengenangkan buruj سرطان Saratdaan/Saratan, yang sepadan dengan ''Cancer'', telah disebut di prasasti Kuala Berang, Terangganu 1303 M).}}
===Etimologi===
Daripada {{der|ms|sa|राशि}}, daripada {{der|ms|inc-pro|*rāśíṣ}}, daripada {{der|ms|iir-pro|*rāćíš}}, daripada {{m|iir-pro|*rać-||mengikat}}.
===Sebutan===
* {{dewan|ra|si}}
* {{rima|ms|si|i}}
===Tulisan Jawi===
{{ARchar|[[راسي]]}}
===Tesaurus===
====Anagram====
* [[siar]], [[iras]]
===Pautan luar===
* {{R:PRPM}}
==Bahasa Indonesia==
===Takrifan===
{{id-noun}}
# {{lb|id|astrologi}} [[buruj]] (kumpulan bintang yang dikatakan menyerupai objek)
:# {{quote-book|id|title=Pengantar Ilmu Falak: Pedoman Lengkap Tentang Teori dan Praktik Hisab, Arah Kiblat, Waktu Salat, Awal Bulan Qamariah & Gerhana
|author=Muhammad Hadi Bashori|year=2015|page=68|text=Bagian-bagian itu disebut '''rasi''' bintang (mintaqatul buruj/''zodiac''/''constelation''). Zodiak ini terdiri dari dua belas (12) '''rasi''' bintang yang membentang disepanjang ekliptika, sehingga seolah-olah merupakan ikat pinggang bola langit.}}
===Etimologi===
Daripada {{der|id|sa|राशि}}, daripada {{der|id|inc-pro|*rāśíṣ}}, daripada {{der|id|iir-pro|*rāćíš}}, daripada {{m|iir-pro|*rać-||mengikat}}.
===Sebutan===
* {{penyempangan|id|ra|si}}
* {{rima|ms|si|i}}
===Pautan luar===
* {{R:KBBI Daring}}
==Bahasa Semai==
===Kata kerja===
{{inti|sea|kata kerja}}
# sental
#: {{cp|sea|Rasi periuk ajeh.|Sental periuk itu.}}
[[Kategori:ms:Astronomi]]
[[Kategori:id:Astronomi]]
3eywljbprh27uvaorjpedkkx8hah5sz
344396
344394
2026-05-26T04:05:45Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344396
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# {{lb|ms|klasik|astrologi}} [[buruj]] (kumpulan bintang yang dikatakan menyerupai objek)
:# {{quote-web|ms|url=http://klikweb.dbp.my/?p=4641|title=Muncul-Lesapnya Konsep dan Istilah Asli Sains dan Matematik dalam Bahasa Melayu Sebelum Abad Kedua Puluh Masihi|date=2013-03-30|work=Dewan Bahasa dan Pustaka|passage=Objek-objek di alam semesta ini, mengikut teori kini, terdiri daripada 88 buah kumpulan bintang (diistiharkan oleh ''International Astronomical Union'', sejak 1928) yang setiap kumpulan bintang ini diistilahkan sebagai '''rasi''' (dalam bahasa Melayu pra-Islam mungkin sekali sejak abad ke-7 M) atau buruj (bahasa Melayu klasik, daripada bahasa Arab, sejak abad ke-12 M mengenangkan buruj سرطان Saratdaan/Saratan, yang sepadan dengan ''Cancer'', telah disebut di prasasti Kuala Berang, Terangganu 1303 M).}}
===Etimologi===
Daripada {{der|ms|sa|राशि}}, daripada {{der|ms|inc-pro|*rāśíṣ}}, daripada {{der|ms|iir-pro|*rāćíš}}, daripada {{m|iir-pro|*rać-||mengikat}}.
===Sebutan===
* {{dewan|ra|si}}
* {{rima|ms|si|i}}
===Tulisan Jawi===
{{ARchar|[[راسي]]}}
===Tesaurus===
====Anagram====
* [[siar]], [[iras]]
===Pautan luar===
* {{R:PRPM}}
==Bahasa Indonesia==
===Takrifan===
{{id-noun}}
# {{lb|id|astrologi}} [[buruj]] (kumpulan bintang yang dikatakan menyerupai objek)
:# {{quote-book|id|title=Pengantar Ilmu Falak: Pedoman Lengkap Tentang Teori dan Praktik Hisab, Arah Kiblat, Waktu Salat, Awal Bulan Qamariah & Gerhana
|author=Muhammad Hadi Bashori|year=2015|page=68|text=Bagian-bagian itu disebut '''rasi''' bintang (mintaqatul buruj/''zodiac''/''constelation''). Zodiak ini terdiri dari dua belas (12) '''rasi''' bintang yang membentang disepanjang ekliptika, sehingga seolah-olah merupakan ikat pinggang bola langit.}}
===Etimologi===
Daripada {{der|id|sa|राशि}}, daripada {{der|id|inc-pro|*rāśíṣ}}, daripada {{der|id|iir-pro|*rāćíš}}, daripada {{m|iir-pro|*rać-||mengikat}}.
===Sebutan===
* {{penyempangan|id|ra|si}}
* {{rima|ms|si|i}}
===Pautan luar===
* {{R:KBBI Daring}}
==Bahasa Semai==
===Kata kerja===
{{inti|sea|kata kerja}}
# sental
#: {{cp|sea|Rasi periuk ajeh.|Sental periuk itu.}}
[[Kategori:ms:Astronomi]]
[[Kategori:id:Astronomi]]
ahp7cyhui4gvqydhl0j2spmlly3m8nv
salam Jumaat
0
17111
344408
340578
2026-05-26T04:07:41Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344408
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata seru===
{{head|ms|kata seru}}
# Suatu [[sapaan]] yang diseru pada hari [[Jumaat]] sebagai rujukan kepada hari Jumaat sebagai hari suci dalam agama Islam.
:# {{quote-web|ms|url=https://www.hmetro.com.my/rap/2020/10/633795/doakan-salma-asis%C2%A0|title=Doakan Salma Asis|date=2020-10-23|work=Harian Metro|passage=Assalamualaikum, '''salam Jumaat'''. Bismillah. Ini bukan Covid-19, bukan juga mengandung. Tapi, hari ini nak buat (jalani) pembedahan kecil.}}
===Etimologi===
Daripada {{compound|ms|salam|Jumaat}}.
===Terjemahan===
{{ter-atas|ucapan}}
* Turki: {{t|tr|hayırlı cumalar}}
{{ter-bawah}}
===Pautan luar===
* {{R:PRPM}}
[[Kategori:ms:Islam]]
3wen4gs5wxqcqssa65bc1wjzfqf5feq
surat cinta
0
17114
344395
333739
2026-05-26T04:04:48Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344395
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# [[Surat]] yang ditulis oleh seseorang untuk meluakhkan perasaan [[cinta]] terhadap seseorang.
# {{lb|ms|ironik|jenaka}} Suatu surat yang mengandungi berita atau kandungan yang berunsur [[malang]] (misalnya [[hukuman]]).
:# {{quote-web|ms|date=2021-02-09|url=https://www.sinarharian.com.my/article/123018/EDISI/Pengusaha-van-sekolah-kecewa-terima-surat-cinta-dari-bank|title=Pengusaha van sekolah kecewa terima 'surat cinta' dari bank|work=Sinar Harian|quote= “Bank cakap tunggu mereka hubungi semula untuk lanjutan moratorium, tapi tiba-tiba ''''surat cinta'''' sampai rumah,” kata seorang pengusaha van sekolah, Abibah Hussin, 62, yang terkejut apabila menerima notis tunggakan peguam minggu lalu.}}
===Etimologi===
Daripada {{compound|ms|surat|cinta}}.
===Sebutan===
* {{dewan|su|rat|cin|ta}}
===Terjemahan===
{{ter-atas|surat meluahkan perasaan cinta}}
* Afrikaans: {{t|af|liefdesbrief}}
* Arab: {{t|ar|رِسَالَةُ حُبٍّ|f}}
* Belanda: {{t+|nl|liefdesbrief|m}}
* Belarusia: {{t|be|любо́ўны ліст|m}}
* Bulgaria: {{t|bg|любо́вно писмо́|n}}
* Burma: {{t+|my|မှာတမ်း|sc=Mymr}}
* Cina:
*: Kantonis: {{t|yue|情書|sc=Hani}}, {{t|yue|情书|tr=cing4 syu1|sc=Hani}}
*: Mandarin: {{t+|cmn|情書|sc=Hani}}, {{t+|cmn|情书|tr=qíngshū|sc=Hani}}
*: Min Nan: {{t|nan|情批|tr=chêng-phoe, chêng-phe|sc=Hani}}
* Czech: {{t|cs|milostný dopis|m}}, {{t|cs|líbesbríf|m}}
* Esperanto: {{t|eo|amoletero}}
* Estonian: {{t|et|armastuskiri}}
* Finnish: {{t+|fi|rakkauskirje}}
* French: {{t|fr|lettre d’amour|f}}
* Gaelik Scotland: {{t|gd|litir-leannanachd|f}}
* Gujarat: {{t|gu|પ્રેમપત્ર}}
* Hindi: {{t|hi|प्रेम पत्र|m}}
* Hungary: {{t|hu|szerelmes levél}}
* Iceland: {{t|is|ástarbréf|n}}
* Iceland: {{t+|en|love letter}}
* Itali: {{t|it|lettera d'amore|f}}
* Jepun: {{t|ja|ラブレター|tr=raburetā|sc=Jpan}}, {{t|ja|恋文|tr=こいぶみ, koibumi|sc=Jpan}}, {{t|ja|付け文|tr=つけぶみ, tsukebumi|sc=Jpan}}
* Jerman: {{t+|de|Liebesbrief|m}}
* Korea: {{t+|ko|연애편지}} ({{t+|ko|戀愛便紙|sc=Kore}}), {{t|ko|련애편지}} {{qualifier|North Korea}}
* Makedonia: {{t|mk|љубовно писмо|n}}
* Marathi: {{t|mr|प्रेम पत्र|n}}
* Ojibwe: {{t|oj|zaagi'iwe-mazina'igan}}
* Parsi: {{t|fa|نامه عاشقانه|tr=nâme-ye 'âšeqâne}}
* Poland: {{t|pl|list miłosny|m}}
* Portugal: {{t|pt|carta amorosa|f}}
* Rusia: {{t|ru|любо́вное письмо́|n}}
* Sepanyol: {{t|es|carta amorosa|f}}, {{t|es|carta de amor|f}}
* Serbo-Croatia:
*: Cyril: {{t|sh|љубавно писмо|n}}
*: Rumi: {{t|sh|ljubavno pismo|n}}
* Slovak: {{t|sk|ľúbostný list|m}}
* Slovenia: {{t|sl|ljubezensko pismo|n}}
* Sweden: {{t+|sv|kärleksbrev}}
* Telugu: {{t|te|ప్రేమలేఖ}}, {{t|te|మన్మథపత్రిక}}
* Thai: {{t|th|จดหมายรัก}}
* Turki: {{t|tr|aşk mektubu}}
* Ukraine: {{t|uk|любо́вний лист|m}}
* Volapük: {{t|vo|lelöfapened}}
* Yunani: {{t|el|ερωτικό γράμμα|n}}
{{ter-bawah}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
[[Kategori:ms:Cinta]]
fnu6euw1alvsin6kgwzhs8388j047ye
344398
344395
2026-05-26T04:06:12Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344398
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# [[Surat]] yang ditulis oleh seseorang untuk meluakhkan perasaan [[cinta]] terhadap seseorang.
# {{lb|ms|ironik|jenaka}} Suatu surat yang mengandungi berita atau kandungan yang berunsur [[malang]] (misalnya [[hukuman]]).
:# {{quote-web|ms|date=2021-02-09|url=https://www.sinarharian.com.my/article/123018/EDISI/Pengusaha-van-sekolah-kecewa-terima-surat-cinta-dari-bank|title=Pengusaha van sekolah kecewa terima 'surat cinta' dari bank|work=Sinar Harian|passage= “Bank cakap tunggu mereka hubungi semula untuk lanjutan moratorium, tapi tiba-tiba ''''surat cinta'''' sampai rumah,” kata seorang pengusaha van sekolah, Abibah Hussin, 62, yang terkejut apabila menerima notis tunggakan peguam minggu lalu.}}
===Etimologi===
Daripada {{compound|ms|surat|cinta}}.
===Sebutan===
* {{dewan|su|rat|cin|ta}}
===Terjemahan===
{{ter-atas|surat meluahkan perasaan cinta}}
* Afrikaans: {{t|af|liefdesbrief}}
* Arab: {{t|ar|رِسَالَةُ حُبٍّ|f}}
* Belanda: {{t+|nl|liefdesbrief|m}}
* Belarusia: {{t|be|любо́ўны ліст|m}}
* Bulgaria: {{t|bg|любо́вно писмо́|n}}
* Burma: {{t+|my|မှာတမ်း|sc=Mymr}}
* Cina:
*: Kantonis: {{t|yue|情書|sc=Hani}}, {{t|yue|情书|tr=cing4 syu1|sc=Hani}}
*: Mandarin: {{t+|cmn|情書|sc=Hani}}, {{t+|cmn|情书|tr=qíngshū|sc=Hani}}
*: Min Nan: {{t|nan|情批|tr=chêng-phoe, chêng-phe|sc=Hani}}
* Czech: {{t|cs|milostný dopis|m}}, {{t|cs|líbesbríf|m}}
* Esperanto: {{t|eo|amoletero}}
* Estonian: {{t|et|armastuskiri}}
* Finnish: {{t+|fi|rakkauskirje}}
* French: {{t|fr|lettre d’amour|f}}
* Gaelik Scotland: {{t|gd|litir-leannanachd|f}}
* Gujarat: {{t|gu|પ્રેમપત્ર}}
* Hindi: {{t|hi|प्रेम पत्र|m}}
* Hungary: {{t|hu|szerelmes levél}}
* Iceland: {{t|is|ástarbréf|n}}
* Iceland: {{t+|en|love letter}}
* Itali: {{t|it|lettera d'amore|f}}
* Jepun: {{t|ja|ラブレター|tr=raburetā|sc=Jpan}}, {{t|ja|恋文|tr=こいぶみ, koibumi|sc=Jpan}}, {{t|ja|付け文|tr=つけぶみ, tsukebumi|sc=Jpan}}
* Jerman: {{t+|de|Liebesbrief|m}}
* Korea: {{t+|ko|연애편지}} ({{t+|ko|戀愛便紙|sc=Kore}}), {{t|ko|련애편지}} {{qualifier|North Korea}}
* Makedonia: {{t|mk|љубовно писмо|n}}
* Marathi: {{t|mr|प्रेम पत्र|n}}
* Ojibwe: {{t|oj|zaagi'iwe-mazina'igan}}
* Parsi: {{t|fa|نامه عاشقانه|tr=nâme-ye 'âšeqâne}}
* Poland: {{t|pl|list miłosny|m}}
* Portugal: {{t|pt|carta amorosa|f}}
* Rusia: {{t|ru|любо́вное письмо́|n}}
* Sepanyol: {{t|es|carta amorosa|f}}, {{t|es|carta de amor|f}}
* Serbo-Croatia:
*: Cyril: {{t|sh|љубавно писмо|n}}
*: Rumi: {{t|sh|ljubavno pismo|n}}
* Slovak: {{t|sk|ľúbostný list|m}}
* Slovenia: {{t|sl|ljubezensko pismo|n}}
* Sweden: {{t+|sv|kärleksbrev}}
* Telugu: {{t|te|ప్రేమలేఖ}}, {{t|te|మన్మథపత్రిక}}
* Thai: {{t|th|จดหมายรัก}}
* Turki: {{t|tr|aşk mektubu}}
* Ukraine: {{t|uk|любо́вний лист|m}}
* Volapük: {{t|vo|lelöfapened}}
* Yunani: {{t|el|ερωτικό γράμμα|n}}
{{ter-bawah}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
[[Kategori:ms:Cinta]]
liig6t6fckoc5thdhjga7fsjtml49k7
terlajak
0
17163
344393
335602
2026-05-26T04:02:11Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344393
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata kerja===
{{ms-kk}}
# {{lb|ms|tak transitif}} Tersasar dari suatu [[sasaran]] atau [[destinasi]] secara tak sengaja.
# {{lb|ms|tak transitif}} Hilang kawalan dalam kata-kata sehingga terlepas cakap sesuatu secara tak sengaja.
====Adverba====
{{head|ms|adverba}}
# {{lb|ms|slanga}} Penekanan terhadap suatu sifat; [[sungguh]], [[sangat]].
:# {{quote-web|ms|url=https://www.bharian.com.my/hujung-minggu/selera/2017/09/326594/laksa-telur-goreng-bersarang|title=Laksa telur goreng bersarang
|date=2017-09-17|work=Berita Harian|passage=Dalam kalangan pelanggan tetap, mereka lebih senang menamakan laksa telur goreng bersarang sebagai laksa sarang saja gara-gara rasanya yang ''''terlajak''' lazat'!
}}
===Etimologi===
Daripada {{prefix|ms|ter|lajak}}.
===Sebutan===
* {{dewan|ter|la|ja/}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
ffg7phg91r52fpg850zf5qdwuzyam0o
menasihatkan
0
17235
344399
339088
2026-05-26T04:06:28Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344399
wikitext
text/x-wiki
==Bahasa Melayu==
===Takrifan===
{{head|ms|kata kerja}}
# memberikan sesuatu sebagai [[nasihat]] atau sebagai tunjuk ajar.
:# {{quote-web|ms|title=Dia bukan polis trafik buat 'part-time'...|url=https://web.archive.org/web/20210311095646/https://www.hmetro.com.my/node/682701/amp|work=Harian Metro|date=2021-03-10|passage=Pihak polis '''menasihatkan''' orang ramai supaya tidak menularkan perkara yang tidak disahkan benar sebelum menyemak perkara berkenaan daripada ditularkan.}}
===Etimologi===
* ''[[me-]]'' + ''[[nasihat]]'' + ''[[kan]]''
===Sebutan===
* {{Dewan|me.na.si.hat.kan}}
===Tulisan Jawi===
* {{ARchar|[[منصيحتکن]]}}
===Rujukan===
* {{R:KP2}}
===Pautan luar===
* {{R:PRPM}}
cthupp987a23mocntx9ui992iev13aq
terpaling
0
17550
344403
341372
2026-05-26T04:06:58Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344403
wikitext
text/x-wiki
==Bahasa Melayu==
===Adverba===
{{head|ms|adverba|Tulisan Jawi|ترڤاليڠ}}
# {{lb|ms|slanga}} Adverba menunjukkan tahap paling tinggi ([[superlatif]]) dalam perbandingan sifat.
#: {{syn|ms|ter-|paling}}
#: {{quote-web|ms|year=2021|url=https://www.hmetro.com.my/mutakhir/2021/03/679666/parcel-rosak-apa-hak-kita-sebagai-pengguna|title=Parcel rosak: Apa hak kita sebagai pengguna?|work=Harian Metro|passage="Perlu juga kita tahu kalau barang yang dibeli secara domestik yang lebih 2.01 kg namun hilang ketika penghantaran, maksimum boleh dituntut hanyalah RM300. Manakala barangan dari luar negara, maksimum RM400 tetapi ganti rugi akan diberikan kepada jumlah '''terpaling''' rendah berdasarkan siasatan dan semakan syarikat kurier," katanya.}}
===Etimologi===
{{prefix|ms|ter|paling}}.
===Sebutan===
* {{dewan|ter|pa|ling}}
* {{rima|ms|liŋ|iŋ}}
===Pautan luar===
* {{R:PRPM}}
n4i05df5qogl81nd7rx3mde3wabugji
warganet
0
17665
344392
334783
2026-05-26T04:01:58Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344392
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# Golongan pengguna [[Internet]] secara am.
#: {{syn|ms|netizen|wargamaya}}
#: {{quote-web|ms|url=https://www.beritaharian.sg/setempat/pm-lee-pesan-agar-warganet-tidak-terpedaya-dengan-akaun-palsu-dirinya-promosi-hadiah|year=2021|title=PM Lee pesan agar warganet tidak terpedaya dengan akaun palsu dirinya promosi 'hadiah percuma'|passage=PERDANA Menteri Lee Hsien Loong mengingatkan '''warganet''' agar tidak terpedaya dengan akaun palsu Facebook yang menayangkan klip beliau kononnya mempromosikan 'hadiah percuma'.|work=Berita Harian Singapura}}
===Etimologi===
{{compound|ms|warga|Internet}}. {{calque|ms|en|netizen}}.
===Sebutan===
* {{dewan|war|ga|nét}}
===Pautan luar===
* {{R:PRPM}}
{{C|ms|Internet}}
==Bahasa Indonesia==
===Kata nama===
{{id-noun}}
# Golongan pengguna [[Internet]] secara am.
#: {{syn|id|netizen}}
#: {{quote-web|id|url=https://tirto.id/perilaku-warganet-indonesia-buktikan-kebenaran-riset-microsoft-gbtg|title=Perilaku Warganet Indonesia Buktikan Kebenaran Riset Microsoft|work=Tirto.id|year=2021|quote=Akun media sosial Microsoft "dihajar" '''warganet''' Indonesia yang tak terima dianggap berperilaku buruk di media sosial.|t=Akaun media sosial Microsoft "dipukul" '''warganet''' Indonesia yang tidak dapat menerima tanggapan perilaku buruk mereka di media sosial.}}
===Etimologi===
{{compound|id|warga|Internet}}. {{calque|id|en|netizen}}.
===Pautan luar===
* {{R:KBBI Daring}}
{{C|ms|Internet}}
16li5b2c9496pexn0zoz00k6buw1vo8
irama Malaysia
0
17686
344390
333949
2026-05-26T03:55:38Z
Hakimi97
2668
344390
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata nama===
{{ms-kn}}
# {{lb|ms|Malaysia}} Sejenis [[genre]] muzik yang mengaplikasikan bunyian alat-alat muzik dan rentak lagu tradisional Malaysia.
#: {{quote-web|ms|url=https://www.bharian.com.my/hiburan/selebriti/2018/09/478968/sanggup-keluar-duit-sendiri-pertahan-irama-malaysia|title='Sanggup keluar duit sendiri pertahan irama Malaysia'|year=2018|work=Berita Harian|passage=Noraniza berkata, arwah pernah menyatakan kebimbangannya terhadap nasib '''irama Malaysia''' yang agak terpinggir apabila tiada anak muda yang berani menggalas tanggungjawab memperjuangkan muzik itu.}}
===Etimologi===
{{compound|ms|irama|Malaysia}}.
===Pautan luar===
* {{R:PRPM}}
{{C|ms|Genre muzik}}
53pwr7zyhb9ademfa8zgux1bd99u38z
prorakyat
0
17794
344405
335441
2026-05-26T04:07:12Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344405
wikitext
text/x-wiki
==Bahasa Melayu==
===Kata sifat===
{{ms-ks|j=ڤرورعيت}}
# {{lb|ms|politik Malaysia}} Mendukung dan menepati atau bersesuaian dengan kehendak [[rakyat]].
#: {{quote-web|ms|title=Umno perlu tampilkan imej parti prorakyat|url=https://www.sinarharian.com.my/politik/umno-perlu-tampilkan-imej-parti-prorakyat-1.590449|work=Sinar Harian|year=2016|passage=Umno perlu tampil dengan imej kukuh sebagai parti '''prorakyat''' dan mengikis persepsi negatif kononnya ia platform untuk mencari 'projek' bagi kepentingan peribadi.}}
===Sebutan===
* {{dewan|pro|ra/|yat}}
===Rujukan===
* {{R:KD4}}
===Pautan luar===
* {{R:PRPM}}
{{C|ms|Politik}}
pgqekqsyjo0002zin4bzlwpbu2oipet
e-hailing
0
17809
344401
320904
2026-05-26T04:06:46Z
Hakimi97
2668
Menggantikan parameter |quote= kepada |passage= berdasarkan kemas kini mutakhir pada [[Modul:quote]] menggunakan [[Project:AWB|AWB]]
344401
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata nama===
{{en-noun|-}}
# {{lb|en|Malaysia}} Perkhidmatan [[teksi]] yang boleh ditempah melalui atas talian (lazimnya menggunakan aplikasi telefon).
#: {{quote-web|en|url=https://www.malaymail.com/news/life/2019/10/21/besides-grab-have-you-heard-of-malaysias-41-other-e-hailing-firms/1802202|title=Besides Grab, have you heard of Malaysia’s 41 other e-hailing firms?|year=2019|work=Malay Mail|passage=The company is currently the most prominent player in the local '''e-hailing''' market, sparking anti-monopoly investigations from the Malaysian Competition Commission after they acquired rival firm Uber’s regional operations in March last year.}}
===Etimologi===
{{prefix|ms|e|hailing}}.
===Sebutan===
* {{penyempangan|en|e|hai|ling}}
nzu8a1jjhvh0i7snrm2i21p7n67wpy3
Modul:la-nominal
828
68094
344383
204835
2026-05-25T23:23:36Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/90371125|90371125]])
344383
Scribunto
text/plain
local export = {}
--[=[
Authorship: Ben Wing <benwing2>, with many ideas and a little code coming from
the old [[Module:la-decl-multi]] by KC Kenny Lau.
]=]
-- TODO:
-- (DONE) Eliminate specification of noteindex from la-adj/data
-- (DONE?) Finish autodetection of adjectives
-- (DONE) Remove old noun code
-- (DONE) Implement <.sufn>
-- (DONE) Look into adj voc=false
-- (DONE) Handle loc in adjectives
-- Error on bad subtypes
-- Make sure Google Books link still works.
-- (DONE) Make sure .sufn triggers insertion of 'with m optionally -> n in compounds' in title.
-- (DONE) Make sure title returned to la-adj lowercases the first letter even with a custom title.
--[=[
TERMINOLOGY:
-- "slot" = A particular case/number combination (for nouns) or
case/number/gender combination (for adjectives). Example slot names are
"abl_sg" (for noun) or "acc_pl_f" (for adjectives). Each slot is filled
with zero or more forms.
-- "form" = The declined Latin form representing the value of a given slot.
For example, rēge is a form, representing the value of the abl_sg slot of
the lemma rēx.
-- "lemma" = The dictionary form of a given Latin term. For nouns, it's
generally the nominative singular, but will be the nominative plural of
plurale tantum nouns (e.g. [[castra]]), and may occasionally be another
form (e.g. the genitive singular) if the nominative singular is missing.
For adjectives, it's generally the masculine nominative singular, but
will be the masculine nominative plural of plurale tantum adjectives
(e.g. [[dēnī]]).
-- "plurale tantum" (plural "pluralia tantum") = A noun or adjective that
exists only in the plural. Examples are castra "army camp", faucēs "throat",
and dēnī "ten each" (used for counting pluralia tantum nouns).
-- "singulare tantum" (plural "singularia tantum") = A noun or adjective that
exists only in the singular. Examples are geōlogia "geology" (and in
general most non-count nouns) and the adjective ūnus "one".
]=]
local debug_track_module = "Module:debug/track"
local en_utilities_module = "Module:en-utilities"
local headword_data_module = "Module:headword/data"
local json_module = "Module:JSON"
local la_adj_data_module = "Module:la-adj/data"
local la_adj_table_module = "Module:la-adj/table"
local la_noun_data_module = "Module:la-noun/data"
local la_noun_table_module = "Module:la-noun/table"
local la_utilities_module = "Module:la-utilities"
local languages_module = "Module:languages"
local links_module = "Module:links"
local load_module = "Module:load"
local parameters_module = "Module:parameters"
local string_utilities_module = "Module:string utilities"
local table_module = "Module:table"
local concat = table.concat
local insert = table.insert
local iter_adj_slots -- defined below
local iter_noun_slots -- defined below
local umatch = mw.ustring.match
local function add_indefinite_article(...)
add_indefinite_article = require(en_utilities_module).add_indefinite_article
return add_indefinite_article(...)
end
local function contains(...)
contains = require(table_module).contains
return contains(...)
end
local function debug_track(...)
debug_track = require(debug_track_module)
return debug_track(...)
end
local function deep_copy(...)
deep_copy = require(table_module).deepCopy
return deep_copy(...)
end
local function deep_equals(...)
deep_equals = require(table_module).deepEquals
return deep_equals(...)
end
local function full_link(...)
full_link = require(links_module).full_link
return full_link(...)
end
local function insert_if_not(...)
insert_if_not = require(table_module).insertIfNot
return insert_if_not(...)
end
local function lcfirst(...)
lcfirst = require(string_utilities_module).lcfirst
return lcfirst(...)
end
local function load_data(...)
load_data = require(load_module).load_data
return load_data(...)
end
local function make_adj_table(...)
make_adj_table = require(la_adj_table_module).make_table
return make_adj_table(...)
end
local function make_noun_table(...)
make_noun_table = require(la_noun_table_module).make_table
return make_noun_table(...)
end
local function make_noun_table_sg(...)
make_noun_table_sg = require(la_noun_table_module).make_table_sg
return make_noun_table_sg(...)
end
local function make_noun_table_pl(...)
make_noun_table_pl = require(la_noun_table_module).make_table_pl
return make_noun_table_pl(...)
end
local function make_stem2(...)
make_stem2 = require(la_utilities_module).make_stem2
return make_stem2(...)
end
local function normalize_form(...)
normalize_form = require(la_utilities_module).normalize_form
return normalize_form(...)
end
local function pluralize(...)
pluralize = require(en_utilities_module).pluralize
return pluralize(...)
end
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
local function remove_links(...)
remove_links = require(links_module).remove_links
return remove_links(...)
end
local function singularize(...)
singularize = require(en_utilities_module).singularize
return singularize(...)
end
local function split(...)
split = require(string_utilities_module).split
return split(...)
end
local function ucfirst(...)
ucfirst = require(string_utilities_module).ucfirst
return ucfirst(...)
end
local m_adj_decl
local function get_m_adj_decl()
m_adj_decl, get_m_adj_decl = require(la_adj_data_module), nil
return m_adj_decl
end
local m_noun_decl
local function get_m_noun_decl()
m_noun_decl, get_m_noun_decl = require(la_noun_data_module), nil
return m_noun_decl
end
local lang
local function get_lang()
lang, get_lang = require(languages_module).getByCode("la")
return lang
end
local namespace
local function get_namespace()
namespace, get_namespace = load_data(headword_data_module).page.namespace, nil
return namespace
end
local pagename
local function get_pagename()
pagename, get_pagename = load_data(headword_data_module).pagename, nil
return pagename
end
local ligatures = {
['Ae'] = 'Æ',
['ae'] = 'æ',
['Oe'] = 'Œ',
['oe'] = 'œ',
}
local cases = {
"nom", "gen", "acc", "dat", "abl", "voc", "loc"
}
local cases_n = #cases
local nums = {
"sg", "pl"
}
local nums_n = #nums
local genders = {
"m", "f", "n"
}
local genders_n = #genders
local declension_to_english = setmetatable({
["1"] = "first",
["1&2"] = "first and second",
["2"] = "second",
["3"] = "third",
["4"] = "fourth",
["5"] = "fifth",
}, {
__index = function(t, k)
return rawget(t, k:match("^[^+-]*"))
end
})
local number_to_english = {
"one", "two", "three", "four", "five"
}
local linked_prefixes = {
"", "linked_"
}
function export.iter_potential_noun_lemma_slots()
local num, case = 1, 0
return function()
case = case + 1
if case > 3 then
case = 1
num = num + 1
if num > nums_n then
return nil
end
end
return cases[case] .. "_" .. nums[num]
end
end
local potential_noun_lemma_slots = {}
for slot in export.iter_potential_noun_lemma_slots() do
insert(potential_noun_lemma_slots, slot)
end
local linked_to_non_linked_noun_slots = {}
for _, slot in ipairs(potential_noun_lemma_slots) do
linked_to_non_linked_noun_slots["linked_" .. slot] = slot
end
-- Iterate over all the "slots" associated with a noun declension, where a slot
-- is a particular case/number combination. If overridable_only, don't include the
-- "linked_" variants (linked_nom_sg, linked_nom_pl), which aren't overridable.
function export.iter_noun_slots(overridable_only)
local case, num, linked_variant = 1, 1, 0
return function()
linked_variant = linked_variant + 1
local max_linked_variant = (overridable_only or case > 3) and 1 or 2
if linked_variant > max_linked_variant then
linked_variant = 1
num = num + 1
if num > nums_n then
num = 1
case = case + 1
if case > cases_n then
return nil
end
end
end
return linked_prefixes[linked_variant] .. cases[case] .. "_" .. nums[num]
end
end
iter_noun_slots = export.iter_noun_slots
function export.iter_potential_adj_lemma_slots()
local num, case, gen = 1, 1, 0
return function()
gen = gen + 1
if gen > genders_n then
gen = 1
case = case + 1
if case > 3 then
case = 1
num = num + 1
if num > nums_n then
return nil
end
end
end
return cases[case] .. "_" .. nums[num] .. "_" .. genders[gen]
end
end
-- List of adjective slots for which we generate linked variants. Include
-- feminine and neuter variants because they will be needed if the adjective
-- is part of a multiword feminine or neuter noun.
local potential_adj_lemma_slots = {}
for slot in export.iter_potential_adj_lemma_slots() do
insert(potential_adj_lemma_slots, slot)
end
local linked_to_non_linked_adj_slots = {}
for _, slot in ipairs(potential_adj_lemma_slots) do
linked_to_non_linked_adj_slots["linked_" .. slot] = slot
end
-- Iterate over all the "slots" associated with an adjective declension, where a slot
-- is a particular case/number/gender combination. If overridable_only, don't include the
-- "linked_" variants (linked_nom_sg_m, linked_nom_pl_m, etc.), which aren't overridable.
function export.iter_adj_slots(overridable_only)
local case, num, gen, linked_variant = 1, 1, 1, 0
return function()
linked_variant = linked_variant + 1
local max_linked_variant = (overridable_only or case > 3) and 1 or 2
if linked_variant > max_linked_variant then
linked_variant = 1
gen = gen + 1
if gen > genders_n then
gen = 1
num = num + 1
if num > nums_n then
num = 1
case = case + 1
if case > cases_n then
return nil
end
end
end
end
return linked_prefixes[linked_variant] .. cases[case] .. "_" .. nums[num] .. "_" .. genders[gen]
end
end
iter_adj_slots = export.iter_adj_slots
-- Iterate over all the "slots" associated with a noun or adjective declension (depending on
-- the value of IS_ADJ), where a slot is a particular case/number combination (in the case of
-- nouns) or case/number/gender combination (in the case of adjectives). If OVERRIDABLE_ONLY
-- is specified, only include overridable slots (not including linked_ variants).
local function iter_slots(is_adj, overridable_only)
if is_adj then
return iter_adj_slots(overridable_only)
end
return iter_noun_slots(overridable_only)
end
local function concat_forms_in_slot(forms)
if forms and forms ~= "" and forms ~= "—" and #forms > 0 then
local new_vals = {}
for _, v in ipairs(forms) do
insert(new_vals, (v:gsub("|", "<!>")))
end
return concat(new_vals, ",")
end
end
local function glossary_link(anchor, text)
text = text or anchor
return "[[Appendix:Glossary#" .. anchor .. "|" .. text .. "]]"
end
local function track(page)
debug_track("la-nominal/" .. page)
return true
end
local function set_union(sets)
local union = {}
for _, set in ipairs(sets) do
for key, _ in pairs(set) do
union[key] = true
end
end
return union
end
local function set_difference(set1, set2)
local diff = {}
for key, _ in pairs(set1) do
if not set2[key] then
diff[key] = true
end
end
return diff
end
-- If a form is set as '*', that means it is unattested
-- but should still be generated
-- TODO: handle asterisks in forms stored in the data
local function unattested_forms(data, args, is_adj)
for slot in iter_slots(is_adj) do
local arg = args[slot]
if arg ~= nil then
arg = arg:match("^*(.*)")
if arg then
data.unattested[slot] = true
args[slot] = arg ~= "" and arg or nil
end
end
end
end
-- Make a link only if the form is attested
local function link_if_attested(form, accel, is_unattested)
local data = {lang = lang or get_lang()}
if is_unattested then
data.alt = "*" .. form
else
data.term = form
data.accel = accel
end
return full_link(data)
end
local function process_form(slot, data, args, linked_to_non_linked)
local forms = data.forms
-- If nomf=1 passed, clear out all masculine and feminine forms.
if data.nomf and slot:match("%f[^%z_][mf]%f[%z_]") then
forms[slot] = nil
end
-- If noneut=1 passed, clear out all neuter forms.
if data.noneut and slot:match("%f[^%z_]n%f[%z_]") then
forms[slot] = nil
end
local val
if args[slot] then
val = args[slot]
data.user_specified[slot] = true
else
-- Overridding nom_sg/nom_sg_m etc. should override linked_nom_sg
-- so that the correct value gets displayed in the headword, which
-- uses linked_nom_sg.
local non_linked_equiv_slot = linked_to_non_linked[slot]
if non_linked_equiv_slot and args[non_linked_equiv_slot] then
val = args[non_linked_equiv_slot]
data.user_specified[slot] = true
else
val = forms[slot]
end
end
if val then
if type(val) == "string" then
val = split(val, "/", true, true)
end
local num = data.num
if (
(num == "pl" and slot:find("sg", nil, true)) or
(num == "sg" and slot:find("pl", nil, true))
) then
forms[slot] = nil
elseif val[1] == "" or val[1] == "-" or val[1] == "—" then
forms[slot] = "—"
if val[2] then
error("Cannot specify additional forms for " .. slot .. ' if it has been cancelled with "-"')
end
else
forms[slot] = val
end
end
end
local function process_noun_forms_and_overrides(data, args, generate_type)
local redlink = false
unattested_forms(data, args);
-- Process overrides and canonicalize forms.
for slot in iter_noun_slots() do
process_form(slot, data, args, linked_to_non_linked_noun_slots)
end
-- No accel forms or red link checking if generate_type == "bare".
if generate_type == "bare" then
return
end
-- Compute the lemma for accelerators. Do this after processing
-- overrides in case we overrode the lemma form(s).
local accel_lemma
if data.num and data.num ~= "" then
accel_lemma = data.forms["nom_" .. data.num]
else
accel_lemma = data.forms["nom_sg"]
end
if type(accel_lemma) == "table" then
accel_lemma = accel_lemma[1]
end
-- Set the accelerators, and determine if there are red links.
for slot in iter_noun_slots() do
local val = data.forms[slot]
if val and val ~= "" and val ~= "—" and #val > 0 then
for _, form in ipairs(val) do
local accel_form = slot
accel_form = accel_form:gsub("_([sp])[gl]$", "|%1")
data.accel[slot] = {form = accel_form, lemma = accel_lemma}
if not redlink and namespace == "" and not form:find("%[") then
local lang = lang or get_lang()
local title = lang:logicalToPhysical(lang:stripDiacritics(form))
local t = mw.title.new(title)
if t and not t.exists then
insert(data.categories, lang:getCanonicalName() .. " " .. data.pos ..
" with red links in their inflection tables")
redlink = true
end
end
end
end
end
end
local function process_adj_forms_and_overrides(data, args, generate_type)
local redlink = false
unattested_forms(data, args, true)
-- Process overrides and canonicalize forms.
for slot in iter_adj_slots() do
process_form(slot, data, args, linked_to_non_linked_adj_slots)
end
-- See if the masculine and feminine/neuter are the same across all slots.
-- If so, blank out the feminine/neuter so we use a table that combines
-- masculine and feminine, or masculine/feminine/neuter.
for _, gender in ipairs({"f", "n"}) do
local other_is_masc = true
for _, case in ipairs(cases) do
for _, num in ipairs(nums) do
if not deep_equals(data.forms[case .. "_" .. num .. "_" .. gender],
data.forms[case .. "_" .. num .. "_m"]) then
other_is_masc = false
break
end
end
if not other_is_masc then
break
end
end
if other_is_masc then
for _, case in ipairs(cases) do
for _, num in ipairs(nums) do
data.forms[case .. "_" .. num .. "_" .. gender] = nil
end
end
end
end
-- No accel forms or red link checking if generate_type == "bare".
if generate_type == "bare" then
return
end
-- Compute the lemma for accelerators. Do this after processing
-- overrides in case we overrode the lemma form(s).
local accel_lemma, accel_lemma_f
if data.num and data.num ~= "" then
accel_lemma = data.forms["nom_" .. data.num .. "_m"]
accel_lemma_f = data.forms["nom_" .. data.num .. "_f"]
else
accel_lemma = data.forms["nom_sg_m"]
accel_lemma_f = data.forms["nom_sg_f"]
end
if type(accel_lemma) == "table" then
accel_lemma = accel_lemma[1]
end
if type(accel_lemma_f) == "table" then
accel_lemma_f = accel_lemma_f[1]
end
-- Set the accelerators, and determine if there are red links.
for slot in iter_adj_slots() do
local val = data.forms[slot]
if val and val ~= "" and val ~= "—" and val[1] then
for _, form in ipairs(val) do
-- FIXME: We should skip accelerators entirely if there are embedded links in the form.
-- FIXME: Even better, make the accelerator code do that automatically.
local accel_form = slot
accel_form = accel_form:gsub("_([sp])[gl]_", "|%1|")
if data.noneut then
-- If noneut=1, we're being asked to do a noun like
-- Aquītānus or Rōmānus that has masculine and feminine
-- variants, not an adjective. In that case, make the
-- accelerators correspond to nominal case/number forms
-- without the gender, and use the feminine as the
-- lemma for feminine forms.
if slot:find("_f", nil, true) then
data.accel[slot] = {form = accel_form:gsub("|f$", ""), lemma = accel_lemma_f}
else
data.accel[slot] = {form = accel_form:gsub("|m$", ""), lemma = accel_lemma}
end
else
if not data.forms.nom_sg_n and not data.forms.nom_pl_n then
-- use multipart tags if called for
accel_form = accel_form:gsub("|m$", "|m//f//n")
elseif not data.forms.nom_sg_f and not data.forms.nom_pl_f then
accel_form = accel_form:gsub("|m$", "|m//f")
end
-- use the order nom|m|s, which is more standard than nom|s|m
accel_form = accel_form:gsub("|(.-)|(.-)$", "|%2|%1")
data.accel[slot] = {form = accel_form, lemma = accel_lemma}
end
if not redlink and namespace == "" and not form:find("%[") then
local lang = lang or get_lang()
local title = lang:logicalToPhysical(lang:stripDiacritics(form))
local t = mw.title.new(title)
if t and not t.exists then
insert(data.categories, lang:getCanonicalName() .. " " .. data.pos ..
" with red links in their inflection tables")
redlink = true
end
end
end
end
end
end
-- Convert data.forms[slot] for all slots into displayable text. This is
-- an older function, still currently used for nouns but not for adjectives.
-- For adjectives, the adjective table module has special code to combine
-- adjacent slots, and needs the original forms plus other text that will
-- go into the displayable text for the slot; this is handled below by
-- partial_show_forms() and finish_show_form().
local function show_forms(data, is_adj)
local noteindex = 1
local notes = {}
local seen_notes = {}
for slot in iter_slots(is_adj) do
local val = data.forms[slot]
if val and val ~= "" and val ~= "—" then
for i, form in ipairs(val) do
local link = link_if_attested(form, data.accel[slot], data.unattested[slot])
local this_notes = data.notes[slot .. i]
if this_notes and not data.user_specified[slot] then
if type(this_notes) == "string" then
this_notes = {this_notes}
end
local link_indices = {}
for _, this_note in ipairs(this_notes) do
local this_noteindex = seen_notes[this_note]
if not this_noteindex then
-- Generate a footnote index.
this_noteindex = noteindex
noteindex = noteindex + 1
insert(notes, '<sup style="color: var(--wikt-palette-red,red)">' .. this_noteindex .. '</sup>' .. this_note)
seen_notes[this_note] = this_noteindex
end
insert_if_not(link_indices, this_noteindex)
end
val[i] = link .. '<sup style="color: var(--wikt-palette-red,red)">' .. concat(link_indices, ",") .. '</sup>'
else
val[i] = link
end
end
-- FIXME, do we want this difference?
data.forms[slot] = concat(val, is_adj and ", " or "<br />")
end
end
for _, footnote in ipairs(data.footnotes) do
insert(notes, footnote)
end
data.footnotes = concat(notes, "<br />")
end
-- Generate the display form for a set of slots with identical content. We
-- verify that the slots are actually identical, and throw an assertion error
-- if not. The display form is as in show_forms() but combines together all the
-- accelerator forms for all the slots.
local function finish_show_form(data, slots, is_adj)
assert(#slots > 0)
local slot1 = slots[1]
local forms = data.forms[slot1]
local notetext = data.notetext[slot1]
for _, slot in ipairs(slots) do
if not deep_equals(data.forms[slot], forms) then
error("data.forms[" .. slot1 .. "] = " .. (concat_forms_in_slot(forms) or "nil") ..
", but data.forms[" .. slot .. "] = " .. (concat_forms_in_slot(data.forms[slot]) or "nil"))
end
assert(deep_equals(data.notetext[slot], notetext))
end
if not forms then
return "—"
else
local accel_forms = {}
local accel_lemma = data.accel[slot1].lemma
for _, slot in ipairs(slots) do
assert(data.accel[slot].lemma == accel_lemma)
insert(accel_forms, data.accel[slot].form)
end
local combined_accel_form = concat(accel_forms, "|;|")
local accel = {form = combined_accel_form, lemma = accel_lemma}
local formtext = {}
for i, form in ipairs(forms) do
insert(formtext, link_if_attested(form, accel, data.unattested[slot1]) .. notetext[i])
end
-- FIXME, do we want this difference?
return concat(formtext, is_adj and ", " or "<br />")
end
end
-- Used by the adjective table module. This does some of the work of
-- show_forms(); in particular, it converts all empty forms of any format
-- (nil, "", "—") to nil and, if the forms aren't empty, generates the footnote
-- text associated with each form.
local function partial_show_forms(data, is_adj)
local noteindex = 1
local notes = {}
local seen_notes = {}
data.notetext = {}
-- Store this function in DATA so that it can be called from the adjective
-- table module without needing to require this module, which will (or
-- could) lead to recursive module requiring.
data.finish_show_form = finish_show_form
for slot in iter_slots(is_adj) do
local val = data.forms[slot]
if not val or val == "" or val == "—" then
data.forms[slot] = nil
else
local notetext = {}
for i in ipairs(val) do
local this_notes = data.notes[slot .. i]
if this_notes and not data.user_specified[slot] then
if type(this_notes) == "string" then
this_notes = {this_notes}
end
local link_indices = {}
for _, this_note in ipairs(this_notes) do
local this_noteindex = seen_notes[this_note]
if not this_noteindex then
-- Generate a footnote index.
this_noteindex = noteindex
noteindex = noteindex + 1
insert(notes, '<sup style="color: var(--wikt-palette-red,red)">' .. this_noteindex .. '</sup>' .. this_note)
seen_notes[this_note] = this_noteindex
end
insert_if_not(link_indices, this_noteindex)
end
insert(notetext, '<sup style="color: var(--wikt-palette-red,red)">' .. concat(link_indices, ",") .. '</sup>')
else
insert(notetext, "")
end
end
data.notetext[slot] = notetext
end
end
for _, footnote in ipairs(data.footnotes) do
insert(notes, footnote)
end
data.footnotes = concat(notes, "<br />")
end
-- Given an ending (or possibly a full regex matching the entire lemma, if
-- a regex group is present), return the base minus the ending, or nil if
-- the ending doesn't match.
local function extract_base(lemma, ending)
if ending:find("(", nil, true) then
return umatch(lemma, ending)
end
return umatch(lemma, "^(.*)" .. ending .. "$")
end
-- Given ENDINGS_AND_SUBTYPES (a list of pairs of endings with associated
-- subtypes, where each pair consists of a single ending spec and a list of
-- subtypes), check each ending in turn against LEMMA. If it matches, return
-- the pair BASE, STEM2, SUBTYPES where BASE is the remainder of LEMMA minus
-- the ending, STEM2 is as passed in, and SUBTYPES is the subtypes associated
-- with the ending. But don't return SUBTYPES if any of the subtypes in the
-- list is specifically canceled in SPECIFIED_SUBTYPES (a set, i.e. a table
-- where the keys are strings and the value is always true); instead, consider
-- the next ending in turn. If no endings match, throw an error if DECLTYPE is
-- non-nil, mentioning the DECLTYPE (the user-specified declension); but if
-- DECLTYPE is nil, just return nil, nil, nil.
--
-- The ending spec in ENDINGS_AND_SUBTYPES is one of the following:
--
-- 1. A simple string, e.g. "tūdō", specifying an ending.
-- 2. A regex that should match the entire lemma (it should be anchored at
-- the beginning with ^ and at the end with $), and contains a single
-- capturing group to match the base.
-- 3. A pair {SIMPLE_STRING_OR_REGEX, STEM2_ENDING} where
-- SIMPLE_STRING_OR_REGEX is one of the previous two possibilities and
-- STEM2_ENDING is a string specifying the corresponding ending that must
-- be present in STEM2. If this form is used, the combination of
-- base + STEM2_ENDING must exactly match STEM2 in order for this entry
-- to be considered a match. An example is {"is", ""}, which will match
-- lemma == "follis", stem2 == "foll", but not lemma == "lapis",
-- stem2 == "lapid".
local function get_noun_subtype_by_ending(lemma, stem2, decltype, specified_subtypes,
endings_and_subtypes)
for _, ending_and_subtypes in ipairs(endings_and_subtypes) do
local ending = ending_and_subtypes[1]
local subtypes = ending_and_subtypes[2]
local not_this_subtype = false
if (
specified_subtypes.pl and not contains(subtypes, "pl") or
contains(subtypes, "both") and not specified_subtypes.both
) then
-- We now require that plurale tantum terms specify a plural-form lemma.
-- The autodetected subtypes will include 'pl' for such lemmas; if not,
-- we fail this entry. Additionally, if the rule contains 'both', it
-- must be explicitly specified to match.
not_this_subtype = true
else
for _, subtype in ipairs(subtypes) do
-- A subtype is directly canceled by specifying -SUBTYPE.
-- In addition, M or F as a subtype is canceled by N, and
-- vice-versa, but M doesn't cancel F or vice-versa; instead,
-- we simply ignore the conflicting gender specification when
-- constructing the combination of specified and inferred subtypes.
-- The reason for this is that neuters have distinct declensions
-- from masculines and feminines, but masculines and feminines have
-- the same declension, and various nouns in Latin that are
-- normally masculine are exceptionally feminine and vice-versa
-- (nauta, agricola, fraxinus, malus "apple tree", manus, rēs,
-- etc.).
--
-- In addition, sg as a subtype is canceled by pl and vice-versa.
-- It's also possible to specify both, which will override sg but
-- not cancel it (in the sense that it won't prevent the relevant
-- rule from matching). For example, there's a rule specifying that
-- lemmas beginning with a capital letter and ending in -ius take
-- the ius.voci.sg subtypes. Specifying such a lemma with the
-- subtype both will result in the ius.voci.both subtypes, whereas
-- specifying such a lemma with the subtype pl will cause this rule
-- not to match, and it will fall through to a less specific rule
-- that returns just the ius subtype, which will be combined with
-- the explicitly specified pl subtype to produce ius.pl.
if specified_subtypes["-" .. subtype] or
subtype == "N" and (specified_subtypes.M or specified_subtypes.F) or
(subtype == "M" or subtype == "F") and specified_subtypes.N or
subtype == "sg" and specified_subtypes.pl or
subtype == "pl" and specified_subtypes.sg then
not_this_subtype = true
break
end
end
end
if not not_this_subtype then
if type(ending) == "table" then
local lemma_ending = ending[1]
local stem2_ending = ending[2]
local base = extract_base(lemma, lemma_ending)
if base and base .. stem2_ending == stem2 then
return base, stem2, subtypes
end
else
local base = extract_base(lemma, ending)
if base then
return base, stem2, subtypes
end
end
end
end
if decltype then
error("Unrecognized ending for declension-" .. decltype .. " noun: " .. lemma)
end
return nil, nil, nil
end
-- Autodetect the subtype of a noun given all the information specified by the
-- user: lemma, stem2, declension type and specified subtypes. Three values are
-- returned: the lemma base (i.e. the stem of the lemma, as required by the
-- declension functions), the new stem2 and the autodetected subtypes. Note
-- that this will not detect a given subtype if the explicitly specified
-- subtypes are incompatible (i.e. if -SUBTYPE is specified for any subtype
-- that would be returned; or if M or F is specified when N would be returned,
-- and vice-versa; or if pl is specified when sg would be returned, and
-- vice-versa).
--
-- NOTE: This function has intimate knowledge of the way that the declension
-- functions handle subtypes, particularly for the third declension.
local function detect_noun_subtype(lemma, stem2, typ, subtypes)
local base, _
if typ == "1" then
return get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"ām", {"F", "am"}},
{"ās", {"M", "Greek", "Ma"}},
{"ēs", {"M", "Greek", "Me"}},
{"ā", {"F", "Greek", "Fa"}},
{"ē", {"F", "Greek"}},
{"ae", {"F", "pl"}},
-- If the lemma ends in -a and the user said N or -F, then F won't
-- apply, and the second (neuter) -a will apply; if the user said
-- pl, then the third (neuter plural) -a will apply.
{"a", {"F"}},
{"a", {"N"}},
{"a", {"N", "pl"}},
})
elseif typ == "2" then
local detected_subtypes
lemma, stem2, detected_subtypes = get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"^(.*r)$", {"M", "er"}},
{"^(.*v)os$", {"M", "vos"}},
{"^(.*v)om$", {"N", "vom"}},
-- If the lemma ends in -os and the user said N or -M, then M won't
-- apply, and the second (neuter) -os will apply.
{"os", {"M", "Greek"}},
{"os", {"N", "Greek", "us"}},
{"on", {"N", "Greek"}},
-- -ius beginning with a capital letter is assumed a proper name,
-- and takes the voci subtype (vocative in -ī) along with the ius
-- subtype and sg-only. Other nouns in -ius just take the ius
-- subtype. Explicitly specify "sg" so that if .pl is given,
-- this rule won't apply.
{"^(%u.*)[iï]us$", {"M", "ius", "voci", "sg"}},
{"[iï]us", {"M", "ius"}},
{"[iï]um", {"N", "ium"}},
-- If the lemma ends in -us and the user said N or -M, then M won't
-- won't apply, and the second (neuter) -us will apply.
{"us", {"M"}},
{"us", {"N", "us"}},
{"um", {"N"}},
{"[iï]ī", {"M", "ius", "pl"}},
{"[iï]a", {"N", "ium", "pl"}},
-- If the lemma ends in -ī and the user said N or -M, then M won't
-- apply, and the second (neuter) -ī will apply.
{"ī", {"M", "pl"}},
{"ī", {"N", "us", "pl"}},
{"oe", {"M", "Greek", "pl"}},
{"a", {"N", "pl"}},
})
stem2 = stem2 or lemma
return lemma, stem2, detected_subtypes
elseif typ == "3" then
if subtypes.pl then
if subtypes.Greek then
base = lemma:match("^(.*)erēs$")
if base then
return base .. "ēr", base .. "er", {"er"}
end
base = lemma:match("^(.*)ontēs$")
if base then
return base .. "ōn", base .. "ont", {"on"}
end
base = lemma:match("^(.*)es$")
if base then
return base, stem2 or base, {}
end
error("Unrecognized ending for declension-3 plural Greek noun: " .. lemma)
end
base = lemma:match("^(.*)[iï]a$")
if base then
return base, stem2 or base, {"N", "I", "pure"}
end
base = lemma:match("^(.*)a$")
if base then
return base, stem2 or base, {"N"}
end
base = lemma:match("^(.*)ēs$")
if base then
return base, stem2 or base, {}
end
error("Unrecognized ending for declension-3 plural noun: " .. lemma)
end
stem2 = stem2 or make_stem2(lemma)
local detected_subtypes
if subtypes.Greek then
base, _, detected_subtypes = get_noun_subtype_by_ending(lemma, stem2, nil, subtypes, {
{{"is", ""}, {"I"}},
{"ēr", {"er"}},
{"ōn", {"on"}},
})
if base then
return lemma, stem2, detected_subtypes
end
return lemma, stem2, {}
end
if not subtypes.N then
base, _, detected_subtypes = get_noun_subtype_by_ending(lemma, stem2, nil, subtypes, {
{{"^(%u.*pol)is$", ""}, {"F", "polis", "sg", "loc"}},
{{"tūdō", "tūdin"}, {"F"}},
{{"tās", "tāt"}, {"F"}},
{{"tūs", "tūt"}, {"F"}},
{{"tiō", "tiōn"}, {"F"}},
{{"siō", "siōn"}, {"F"}},
{{"xiō", "xiōn"}, {"F"}},
{{"gō", "gin"}, {"F"}},
{{"or", "ōr"}, {"M"}},
{{"tr[iī]x", "trīc"}, {"F"}},
{{"is", ""}, {"I"}},
{{"^(%l.*)ēs$", ""}, {"I"}},
})
if base then
return lemma, stem2, detected_subtypes
end
end
base, _, detected_subtypes = get_noun_subtype_by_ending(lemma, stem2, nil, subtypes, {
{{"us", "or"}, {"N"}},
{{"us", "er"}, {"N"}},
{{"ma", "mat"}, {"N"}},
{{"men", "min"}, {"N"}},
{{"^(%u.*)[eë]$", ""}, {"N", "sg"}},
{{"[eë]", ""}, {"N", "I", "pure"}},
{{"al", "āl"}, {"N", "I", "pure"}},
{{"ar", "ār"}, {"N", "I", "pure"}},
})
if base then
return lemma, stem2, detected_subtypes
end
return lemma, stem2, {}
elseif typ == "4" then
if subtypes.echo or subtypes.Callisto then
base = lemma:match("^(.*)ō$")
if not base then
error("Declension-4 noun of subtype .echo or .Callisto should end in -ō: " .. lemma)
end
if subtypes.Callisto then
return base, nil, {"F", "sg"}
else
return base, nil, {"F"}
end
end
return get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"us", {"M"}},
{"ū̆", {"N"}},
{"ūs", {"M", "pl"}},
{"[uü]a", {"N", "pl"}},
})
elseif typ == "5" then
return get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"[iï]ēs", {"F", "i"}},
{"[iï]ēs", {"F", "i", "pl"}},
{"ēs", {"F"}},
{"ēs", {"F", "pl"}},
})
elseif typ == "sgpl" then
return lemma, stem2, {}
elseif typ == "irreg" and lemma == "domus" then
-- [[domus]] auto-sets data.loc = true, but we need to know this
-- before declining the noun so we can propagate it to other segments.
return lemma, nil, {"loc"}
elseif typ == "indecl" or typ == "irreg" and (
lemma == "Deus" or umatch(lemma, "^[IJ]ēs[uū]s$") or
lemma == "Athōs" or lemma == "vēnum"
) then
-- Indeclinable nouns, and certain irregular nouns, set data.num = "sg",
-- but we need to know this before declining the noun so we can
-- propagate it to other segments.
return get_noun_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"", {"both"}},
{"", {"sg"}},
{"", {"pl"}},
})
else
return lemma, nil, {}
end
end
-- Given ENDINGS_AND_SUBTYPES (a list of four-tuples of ENDING, RETTYPE,
-- SUBTYPES, PROCESS_RETVAL), check each ENDING in turn against LEMMA and
-- STEM2. If it matches, return a four-tuple BASE, STEM2, RETTYPE, NEW_SUBTYPES
-- where BASE is normally the remainder of LEMMA minus the ending, STEM2 is
-- as passed in, RETTYPE is as passed in, and NEW_SUBTYPES is the same as
-- SUBTYPES minus any subtypes beginning with a hyphen. If no endings match,
-- throw an error if DECLTYPPE is non-nil, mentioning the DECLTYPE
-- (user-specified declension); but if DECLTYPE is nil, just return the tuple
-- nil, nil, nil, nil.
--
-- In order for a given entry to match, ENDING must match and also the subtypes
-- in SUBTYPES (a list) must not be incompatible with the passed-in
-- user-specified subtypes SPECIFIED_SUBTYPES (a set, i.e. a table where the
-- keys are strings and the value is always true). "Incompatible" means that
-- a given SUBTYPE is specified in either one and -SUBTYPE in the other, or
-- that "pl" is found in SPECIFIED_SUBTYPES and not in SUBTYPES.
--
-- The ending spec in ENDINGS_AND_SUBTYPES is one of the following:
--
-- 1. A simple string, e.g. "tūdō", specifying an ending.
-- 2. A regex that should match the entire lemma (it should be anchored at
-- the beginning with ^ and at the end with $), and contains a single
-- capturing group to match the base.
-- 3. A pair {SIMPLE_STRING_OR_REGEX, STEM2_ENDING} where
-- SIMPLE_STRING_OR_REGEX is one of the previous two possibilities and
-- STEM2_ENDING is a string specifying the corresponding ending that must
-- be present in STEM2. If this form is used, the combination of
-- base + STEM2_ENDING must exactly match STEM2 in order for this entry
-- to be considered a match. An example is {"is", ""}, which will match
-- lemma == "follis", stem2 == "foll", but not lemma == "lapis",
-- stem2 == "lapid".
--
-- If PROCESS_STEM2 is given and the returned STEM2 would be nil, call
-- process_stem2(BASE) to get the STEM2 to return.
local function get_adj_type_and_subtype_by_ending(lemma, stem2, decltype,
specified_subtypes, endings_and_subtypes, process_stem2)
for _, ending_and_subtypes in ipairs(endings_and_subtypes) do
local ending = ending_and_subtypes[1]
local rettype = ending_and_subtypes[2]
local subtypes = ending_and_subtypes[3]
local process_retval = ending_and_subtypes[4]
local not_this_subtype = false
if (
specified_subtypes.pl and not contains(subtypes, "pl") or
contains(subtypes, "both") and not specified_subtypes.both
) then
-- We now require that plurale tantum terms specify a plural-form lemma.
-- The autodetected subtypes will include 'pl' for such lemmas; if not,
-- we fail this entry. Additionally, if the rule contains 'both', it
-- must be explicitly specified to match.
not_this_subtype = true
else
for _, subtype in ipairs(subtypes) do
-- A subtype is directly canceled by specifying -SUBTYPE.
if specified_subtypes["-" .. subtype] then
not_this_subtype = true
break
end
-- A subtype is canceled if the user specified SUBTYPE and
-- -SUBTYPE is given in the to-be-returned subtypes.
local must_not_be_present = subtype:match("^%-(.*)$")
if must_not_be_present and specified_subtypes[must_not_be_present] then
not_this_subtype = true
break
end
end
end
if not not_this_subtype then
local base
if type(ending) == "table" then
local lemma_ending = ending[1]
local stem2_ending = ending[2]
base = extract_base(lemma, lemma_ending)
if base and base .. stem2_ending ~= stem2 then
base = nil
end
else
base = extract_base(lemma, ending)
end
if base then
-- Remove subtypes of the form -SUBTYPE from the subtypes
-- to be returned.
local new_subtypes = {}
for _, subtype in ipairs(subtypes) do
if subtype:sub(1, 1) ~= "-" then
insert(new_subtypes, subtype)
end
end
if process_retval then
base, stem2 = process_retval(base, stem2)
end
if process_stem2 then
stem2 = stem2 or process_stem2(base)
end
return base, stem2, rettype, new_subtypes
end
end
end
if not decltype then
return nil, nil, nil, nil
elseif decltype == "" then
error("Unrecognized ending for adjective: " .. lemma)
else
error("Unrecognized ending for declension-" .. decltype .. " adjective: " .. lemma)
end
end
-- Autodetect the type and subtype of an adjective given all the information
-- specified by the user: lemma, stem2, declension type and specified subtypes.
-- Four values are returned: the lemma base (i.e. the stem of the lemma, as
-- required by the declension functions), the value of stem2 to pass to the
-- declension function, the declension type and the autodetected subtypes.
-- Note that this will not detect a given subtype if -SUBTYPE is specified for
-- any subtype that would be returned, or if SUBTYPE is specified and -SUBTYPE
-- is among the subtypes that would be returned (such subtypes are filtered out
-- of the returned subtypes).
local function detect_adj_type_and_subtype(lemma, stem2, typ, subtypes)
local function base_as_stem2(base, stem2)
return base, base
end
local function constant_base(baseval)
return function(base, stem2)
return baseval, nil
end
end
local function decl12_stem2(base)
return base
end
local function decl3_stem2(base)
return make_stem2(base)
end
local decl12_entries = {
{"us", "1&2+", {}},
{"a", "1&2+", {}},
{"um", "1&2+", {}},
{"ī", "1&2+", {"pl"}},
{"ae", "1&2+", {"pl"}},
{"a", "1&2+", {"pl"}},
-- Nearly all -os adjectives are greekA
{"os", "1&2+", {"greekA", "-greekE"}},
{"os", "1&2+", {"greekE", "-greekA"}},
{"ē", "1&2+", {"greekE", "-greekA"}},
{"on", "1&2+", {"greekA", "-greekE"}},
{"on", "1&2+", {"greekE", "-greekA"}},
{"^(.*er)$", "1&2+", {"er"}},
{"^(.*ur)$", "1&2+", {"er"}},
{"^(h)ic$", "1&2+", {"ic"}},
}
local decl3_entries = {
{"^(.*er)$", "3-3+", {"I"}},
{"^(.*er)$", "3-3+", {}},
{"is", "3-2+", {"I"}},
{"is", "3-2+", {}},
{"e", "3-2+", {"I"}},
{"e", "3-2+", {}},
{"^(.*[iïj])or$", "3-C+", {"abl_e_i", "-abl_i_e"}},
{"^(.*[iïj])or$", "3-C+", {}},
{"^(min)or$", "3-C+", {"abl_e_i", "-abl_i_e"}},
{"^(min)or$", "3-C+", {}},
{"^(.*trīx)$", "3-def+", {"trix", "abl_i_e", "-abl_e_i"}},
{"^(.*trīx)$", "3-def+", {"trix"}},
{"^(.*tor)$", "3-def+", {"tor", "abl_i_e", "-abl_e_i"}},
{"^(.*tor)$", "3-def+", {"tor"}},
-- Detect -ēs as 3-1 without auto-inferring .pl if .pl
-- not specified. If we don't do this, the later entry for
-- -ēs will auto-infer .pl whenever -ēs is specified (which
-- won't work for adjectives like quadripēs, volucripēs).
-- Essentially, for declension-3 adjectives, we require that
-- .pl is given if the lemma is plural.
--
-- Most 3-1 adjectives are i-stem (e.g. audāx) so we require -I
-- to be given with non-i-stem adjectives. The first entry below
-- will apply when -I isn't given, the second when it is given.
{"^(.*ēs)$", "3-1+", {"I", "abl_i_e", "-abl_e_i"}},
{"^(.*ēs)$", "3-1+", {"I"}},
{"^(.*ēs)$", "3-1+", {"par", "abl_i_e", "-abl_e_i"}},
{"^(.*ēs)$", "3-1+", {"par"}},
{"^(.*[iïj])ōrēs$", "3-C+", {"pl"}},
{"^(min)ōrēs$", "3-C+", {"pl"}},
-- If .pl with -ēs, we don't know if the adjective is 3-1, 3-2
-- or 3-3. Since 3-2 is probably the most common, we infer it
-- (as well as the fact that these adjectives *are* in a sense
-- 3-2 since they have a distinct neuter in -(i)a. Note that
-- we have two entries here; the first one will apply unless
-- -I is given, and will infer an i-stem adjective; the second
-- one will apply otherwise (and infer a non-i-stem 3-1 adjective).
{"ēs", "3-2+", {"pl", "I"}, base_as_stem2},
{"ēs", "3-1+", {"pl", "par"}, base_as_stem2},
-- Same for neuters.
{"ia", "3-2+", {"pl", "I"}, base_as_stem2},
{"a", "3-1+", {"pl", "par"}, base_as_stem2},
-- As above for -ēs but for miscellaneous singulars.
{"", "3-1+", {"I", "abl_i_e", "-abl_e_i"}},
{"", "3-1+", {"I"}},
{"", "3-1+", {"par", "abl_i_e", "-abl_e_i"}},
{"", "3-1+", {"par"}},
}
local function get_subtypes_and_endings(typ, f)
local subtypes_and_endings = {}
for _, v in ipairs(decl3_entries) do
if f(v) then
v = deep_copy(v)
v[2] = typ
insert(subtypes_and_endings, v)
end
end
return subtypes_and_endings
end
local function compare(spec)
return spec[2] == typ
end
if typ == "+" then
local base, new_stem2, rettype, new_subtypes = get_adj_type_and_subtype_by_ending(lemma, stem2, nil, subtypes, decl12_entries, decl12_stem2)
if base then
return base, new_stem2, rettype, new_subtypes
else
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, decl3_entries, decl3_stem2)
end
elseif typ == "3+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, decl3_entries, decl3_stem2)
elseif typ == "1&2+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, decl12_entries, decl12_stem2)
elseif typ == "1-1+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"a", typ, {}},
{"ae", typ, {"pl"}},
})
elseif typ == "2-2+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"us", typ, {}},
{"um", typ, {}},
{"ī", typ, {"pl"}},
{"a", typ, {"pl"}},
{"os", typ, {"greek"}},
{"on", typ, {"greek"}},
{"oe", typ, {"greek", "pl"}},
})
elseif typ == "3-1+" then
-- Use the specs from `decl3_entries`, but add the two i-stem 3-2+ specs when plural-only, as they're the same when 3-1+.
local subtypes_and_endings = get_subtypes_and_endings(typ, function(spec)
local spec1, spec2 = spec[1], spec[2]
return spec2 == typ or (spec2 == "3-2+" and spec1 == "ēs" or spec1 == "ia")
end)
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, subtypes_and_endings, decl3_stem2)
elseif typ == "3-def+" then
-- Like 3-1+ but defective in gender
local subtypes_and_endings = get_subtypes_and_endings(typ, compare)
insert(subtypes_and_endings, {"", typ, {"I"}})
insert(subtypes_and_endings, {"", typ, {"par"}})
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, subtypes_and_endings, decl3_stem2)
elseif typ == "3-2+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"is", typ, {}},
{"e", typ, {}},
-- Detect -ēs as 3-2 without auto-inferring .pl if .pl
-- not specified. If we don't do this, the later entry for
-- -ēs will auto-infer .pl whenever -ēs is specified (which
-- won't work for adjectives like isoscelēs). Essentially,
-- for declension-3 adjectives, we require that .pl is given
-- if the lemma is plural.
{"ēs", typ, {}},
{"ēs", typ, {"pl"}},
{"ia", typ, {"pl"}},
}, decl3_stem2)
elseif typ == "3-3+" or typ == "3-P+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"ēs", typ, {"pl"}, base_as_stem2},
{"ia", typ, {"pl"}, base_as_stem2},
{"", typ, {}},
}, decl3_stem2)
elseif typ == "3-C+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, get_subtypes_and_endings(typ, compare), decl3_stem2)
elseif typ == "irreg+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"^(duo)$", typ, {"pl"}},
{"^(ambō)$", typ, {"pl"}},
{"^(mīll?ia)$", typ, {"N", "pl"}, constant_base("mīlle")},
-- match ea
{"^(ea)$", typ, {}, constant_base("is")},
-- match id
{"^(id)$", typ, {}, constant_base("is")},
-- match plural eī, iī
{"^([ei]ī)$", typ, {"pl"}, constant_base("is")},
-- match plural ea, eae
{"^(eae?)$", typ, {"pl"}, constant_base("is")},
-- match eadem
{"^(eadem)$", typ, {}, constant_base("īdem")},
-- match īdem, idem
{"^([īi]dem)$", typ, {}, constant_base("īdem")},
-- match plural īdem
{"^(īdem)$", typ, {"pl"}},
-- match plural eadem, eaedem
{"^(eae?dem)$", typ, {"pl"}, constant_base("īdem")},
-- match illa, ipsa, ista; it doesn't matter if we overmatch because
-- we'll get an error as we use the stem itself in the returned base
{"^(i[lps][lst])a$", typ, {}, function(base, stem2) return base .. "e", nil end},
-- match illud, istud; as above, it doesn't matter if we overmatch
{"^(i[ls][lt])ud$", typ, {}, function(base, stem2) return base .. "e", nil end},
-- match ipsum
{"^(ipsum)$", typ, {}, constant_base("ipse")},
-- match plural illī, ipsī, istī; as above, it doesn't matter if we
-- overmatch
{"^(i[lps][lst])ī$", typ, {"pl"}, function(base, stem2) return base .. "e", nil end},
-- match plural illa, illae, ipsa, ipsae, ista, istae; as above, it
-- doesn't matter if we overmatch
{"^(i[lps][lst])ae?$", typ, {"pl"}, function(base, stem2) return base .. "e", nil end},
-- Detect quī as non-plural unless .pl specified.
{"^(quī)$", typ, {}},
-- Otherwise detect quī as plural.
{"^(quī)$", typ, {"pl"}},
-- Same for quae.
{"^(quae)$", typ, {}, constant_base("quī")},
{"^(quae)$", typ, {"pl"}, constant_base("quī")},
{"^(quid)$", typ, {}, constant_base("quis")},
{"^(quod)$", typ, {}, constant_base("quī")},
{"^(qui[cd]quid)$", typ, {}, constant_base("quisquis")},
{"^(quīquī)$", typ, {"pl"}, constant_base("quisquis")},
{"^(quaequae)$", typ, {"pl"}, constant_base("quisquis")},
-- match all remaining lemmas in lemma form
{"", typ, {}},
})
elseif typ == "indecl+" then
return get_adj_type_and_subtype_by_ending(lemma, stem2, typ, subtypes, {
{"", typ, {"both"}},
{"", typ, {"sg"}},
{"", typ, {"pl"}},
})
else -- 0+
return lemma, nil, typ, {}
end
end
-- Parse a segment (e.g. "lūna<1>", "aegis/aegid<3.Greek>", "bōs<irreg.F>",
-- bonus<+>", or "[[vetus]]/veter<3+.-I>"), consisting of a lemma (or optionally
-- a lemma/stem) and declension+subtypes, where a + in the declension indicates
-- an adjective. Brackets can be present to indicate links, for use in
-- {{la-noun}} and {{la-adj}}. The return value is a table, e.g.:
-- {
-- decl = "1",
-- is_adj = false,
-- orig_lemma = "lūna",
-- lemma = "lūna",
-- stem2 = nil,
-- gender = "F",
-- types = {["F"] = true},
-- args = {"lūn"}
-- }
--
-- or
--
-- {
-- decl = "3",
-- is_adj = false,
-- orig_lemma = "aegis",
-- lemma = "aegis",
-- stem2 = "aegid",
-- gender = nil,
-- types = {["Greek"] = true},
-- args = {"aegis", "aegid"}
-- }
--
-- or
--
-- {
-- decl = "irreg",
-- is_adj = false,
-- orig_lemma = "bōs",
-- lemma = "bōs",
-- stem2 = nil,
-- gender = "F",
-- types = {["F"] = true},
-- args = {"bōs"}
-- }
-- or
--
-- {
-- decl = "1&2+",
-- is_adj = true,
-- orig_lemma = "bonus",
-- lemma = "bonus",
-- stem2 = nil,
-- gender = nil,
-- types = {},
-- args = {"bon"}
-- }
--
-- or
--
-- {
-- decl = "3-1+",
-- is_adj = true,
-- orig_lemma = "[[vetus]]",
-- lemma = "vetus",
-- stem2 = "veter",
-- gender = nil,
-- types = {},
-- args = {"vetus", "veter"}
-- }
local function parse_segment(segment)
local stem_part, spec_part = segment:match("^(.*)<(.-)>$")
local stems = split(stem_part, "/", true, true)
local specs = split(spec_part, ".", true, true)
local types = {}
local num = nil
local loc = false
local args = {}
local decl
for j, spec in ipairs(specs) do
if j == 1 then
decl = spec
else
local begins_with_hyphen
begins_with_hyphen, spec = spec:match("^(%-?)(.*)$")
spec = begins_with_hyphen .. spec:gsub("%-", "_")
types[spec] = true
end
end
local orig_lemma = stems[1]
if not orig_lemma or orig_lemma == "" then
orig_lemma = pagename or get_pagename()
end
local lemma = remove_links(orig_lemma)
local stem2 = stems[2]
if stem2 == "" then
stem2 = nil
end
if #stems > 2 then
error("Too many stems, at most 2 should be given: " .. stem_part)
end
local base, detected_subtypes
local is_adj = false
local gender = nil
if decl:find("+", nil, true) then
base, stem2, decl, detected_subtypes = detect_adj_type_and_subtype(lemma, stem2, decl, types)
is_adj = true
for _, subtype in ipairs(detected_subtypes) do
if types["-" .. subtype] then
-- if a "cancel subtype" spec is given, remove the cancel spec
-- and don't apply the subtype
types["-" .. subtype] = nil
else
types[subtype] = true
end
end
else
base, stem2, detected_subtypes = detect_noun_subtype(lemma, stem2, decl, types)
for _, subtype in ipairs(detected_subtypes) do
if types["-" .. subtype] then
-- if a "cancel subtype" spec is given, remove the cancel spec
-- and don't apply the subtype
types["-" .. subtype] = nil
elseif (subtype == "M" or subtype == "F" or subtype == "N") and
(types.M or types.F or types.N) then
-- if gender already specified, don't create conflicting gender spec
elseif (subtype == "sg" or subtype == "pl" or subtype == "both") and
(types.sg or types.pl or types.both) then
-- if number restriction already specified, don't create conflicting
-- number restriction spec
else
types[subtype] = true
end
end
if not types.pl and not types.both and umatch(lemma, "^%u") then
types.sg = true
end
end
if types.loc then
loc = true
types.loc = nil
end
if types.M then
gender = "M"
elseif types.F then
gender = "F"
elseif types.N then
gender = "N"
end
if types.pl then
num = "pl"
types.pl = nil
elseif types.sg then
num = "sg"
types.sg = nil
end
args[1] = base
args[2] = stem2
return {
decl = decl,
is_adj = is_adj,
gender = gender,
orig_lemma = orig_lemma,
lemma = lemma,
stem2 = stem2,
types = types,
num = num,
loc = loc,
args = args,
}
end
-- Parse a segment run (i.e. a string with zero or more segments [see
-- parse_segment] and optional surrounding text, e.g. "foenum<2>-graecum<2>"
-- or "[[pars]]/part<3.abl-e-occ-i> [[oratio|ōrātiōnis]]"). The segment run
-- currently cannot contain any alternants (e.g. "((epulum<2.sg>,epulae<1>))").
-- The return value is a table of the following form:
-- {
-- segments = PARSED_SEGMENTS (a list of parsed segments),
-- loc = LOC (a boolean indicating whether any of the individual segments
-- has a locative),
-- num = NUM (the first specified value for a number restriction, or nil if
-- no number restrictions),
-- gender = GENDER (the first specified or inferred gender, or nil if none),
-- is_adj = IS_ADJ (true if all segments are adjective segments, false if
-- there's at least one noun segment, nil if only raw-text segments),
-- propses = PROPSES (list of per-word properties, where each element is an
-- object {
-- decl = DECL (declension),
-- types = TYPES (set describing the subtypes of a given word),
-- }
-- }
-- Each element in PARSED_SEGMENTS is as returned by parse_segment() but will
-- have an additional .orig_prefix field indicating the text before the segment
-- (including bracketed links) and corresponding .prefix field indicating the text
-- with bracketed links resolved. If there is trailing text, the last element will
-- have only .orig_prefix and .prefix fields containing that trailing text.
local function parse_segment_run(segment_run)
local loc = nil
local num = nil
local is_adj = nil
-- If the segment run begins with a hyphen, include the hyphen in the
-- set of allowed characters for a declined segment. This way, e.g. the
-- suffix [[-cen]] can be declared as {{la-ndecl|-cen/-cin<3>}} rather than
-- {{la-ndecl|-cen/cin<3>}}, which is less intuitive.
local is_suffix = segment_run:sub(1, 1) == "-"
local segments = {}
local propses = {}
-- We want to not break up a bracketed link followed by <> even if it has a space or
-- hyphen in it. So we do an outer capturing split to find the bracketed links followed
-- by <>, then do inner capturing splits on all the remaining text to find the other
-- declined terms.
local bracketed_segments = split(segment_run, "(%[%[[^%[%]]-%]%]<.->)")
for i, bracketed_segment in ipairs(bracketed_segments) do
if i % 2 == 0 then
insert(segments, bracketed_segment)
else
for _, subsegment in ipairs(split(bracketed_segment, is_suffix and "([^<> ,]+<.->)" or "([^<> ,%-]+<.->)")) do
insert(segments, subsegment)
end
end
end
local parsed_segments = {}
local gender = nil
for i = 2, (#segments - 1), 2 do
local parsed_segment = parse_segment(segments[i])
-- Overall locative is true if any segments call for locative.
loc = loc or parsed_segment.loc
-- The first specified value for num is used becomes the overall value.
num = num or parsed_segment.num
if is_adj == nil then
is_adj = parsed_segment.is_adj
else
is_adj = is_adj and parsed_segment.is_adj
end
gender = gender or parsed_segment.gender
parsed_segment.orig_prefix = segments[i - 1]
parsed_segment.prefix = remove_links(segments[i - 1])
parsed_segment.props = {
decl = parsed_segment.decl,
types = parsed_segment.types,
gender = parsed_segment.gender,
num = parsed_segment.num,
}
insert(parsed_segments, parsed_segment)
insert(propses, parsed_segment.props)
end
if segments[#segments] ~= "" then
insert(parsed_segments, {
orig_prefix = segments[#segments],
prefix = remove_links(segments[#segments]),
})
end
return {
segments = parsed_segments,
loc = loc,
num = num,
is_adj = is_adj,
gender = gender,
propses = propses,
}
end
-- Parse an alternant, e.g. "((epulum<2.sg>,epulae<1>))",
-- "((Serapis<3>,Serapis/Serapid<3>))" or
-- "((rēs<5>pūblica<1>,rēspūblica<1>))". The return value is a table of the form
-- {
-- alternants = PARSED_ALTERNANTS (a list of segment runs, each of which is a
-- list of parsed segments as returned by parse_segment_run()),
-- loc = LOC (a boolean indicating whether any of the individual segment runs
-- has a locative),
-- num = NUM (the overall number restriction, one of "sg", "pl" or "both"),
-- gender = GENDER (the first specified or inferred gender, or nil if none),
-- is_adj = IS_ADJ (true if all non-constant alternants are adjectives, false
-- if all nouns, nil if only constant alternants; conflicting alternants
-- cause an error),
-- propses = PROPSES (list of lists of per-word property objecs),
-- }
local function parse_alternant(alternant)
local parsed_alternants = {}
local alternant_spec = alternant:match("^%(%((.-)%)%)$")
local alternants = split(alternant_spec, ",", true, true)
local loc = false
local num = nil
local gender = nil
local is_adj = nil
local propses = {}
for i, alternant in ipairs(alternants) do
local parsed_run = parse_segment_run(alternant)
insert(parsed_alternants, parsed_run)
loc = loc or parsed_run.loc
-- First time through, set the overall num to the num of the first run,
-- even if nil. After that, if we ever see a run with a different value
-- of num, set the overall num to "both". That way, if all alternants
-- don't specify a num, we get an unspecified num, but if some do and
-- some don't, we get both, because an unspecified num defaults to
-- both.
if i == 1 then
num = parsed_run.num
elseif num ~= parsed_run.num then
-- FIXME, this needs to be rethought to allow for
-- adjective alternants.
num = "both"
end
gender = gender or parsed_run.gender
if is_adj == nil then
is_adj = parsed_run.is_adj
elseif parsed_run.is_adj ~= nil and parsed_run.is_adj ~= is_adj then
error("Saw both noun and adjective alternants; not allowed")
end
insert(propses, parsed_run.propses)
end
return {
alternants = parsed_alternants,
loc = loc,
num = num,
gender = gender,
is_adj = is_adj,
propses = propses,
}
end
-- Parse a segment run (see parse_segment_run()). Unlike for
-- parse_segment_run(), this can contain alternants such as
-- "((epulum<2.sg>,epulae<1>))" or "((Serapis<3.sg>,Serapis/Serapid<3.sg>))"
-- embedded in it to indicate words composed of multiple declensions.
-- The return value is a table of the following form:
-- {
-- segments = PARSED_SEGMENTS (a list of parsed segments),
-- loc = LOC (a boolean indicating whether any of the individual segments has
-- a locative),
-- num = NUM (the first specified value for a number restriction, or nil if
-- no number restrictions),
-- gender = GENDER (the first specified or inferred gender, or nil if none),
-- is_adj = IS_ADJ (true if all segments are adjective segments, false if
-- there's at least one noun segment, nil if only raw-text segments),
-- propses = PROPSES (list of either per-word property objects or lists of
-- lists of such objects),
-- }.
-- Each element in PARSED_SEGMENTS is one of three types:
--
-- 1. A regular segment, as returned by parse_segment() but with additional
-- .prefix and .orig_prefix fields indicating the text before the segment, as per
-- the return value of parse_segment_run().
-- 2. A raw-text segment, i.e. a table with only .prefix and .orig_prefix fields
-- containing the raw text.
-- 3. An alternating segment, as returned by parse_alternant().
-- Note that each alternant is a segment run rather than a single parsed
-- segment to allow for alternants like "((rēs<5>pūblica<1>,rēspūblica<1>))".
-- The parsed segment runs in PARSED_SEGMENT_RUNS are tables as returned by
-- parse_segment_run() (of the same form as the overall return value of
-- parse_segment_run_allowing_alternants()).
local function parse_segment_run_allowing_alternants(segment_run)
if segment_run:find(" ", nil, true) then
track("has-space")
end
if segment_run:find("((", nil, true) then
track("has-alternant")
end
local alternating_segments = split(segment_run, "(%(%(.-%)%))")
local parsed_segments = {}
local loc = false
local num = nil
local gender = nil
local is_adj = nil
local propses = {}
for i = 1, #alternating_segments do
local alternating_segment = alternating_segments[i]
if alternating_segment ~= "" then
local this_is_adj
if i % 2 == 1 then
local parsed_run = parse_segment_run(alternating_segment)
for _, parsed_segment in ipairs(parsed_run.segments) do
insert(parsed_segments, parsed_segment)
end
loc = loc or parsed_run.loc
num = num or parsed_run.num
gender = gender or parsed_run.gender
this_is_adj = parsed_run.is_adj
for _, props in ipairs(parsed_run.propses) do
insert(propses, props)
end
else
local parsed_alternating_segment = parse_alternant(alternating_segment)
insert(parsed_segments, parsed_alternating_segment)
loc = loc or parsed_alternating_segment.loc
num = num or parsed_alternating_segment.num
gender = gender or parsed_alternating_segment.gender
this_is_adj = parsed_alternating_segment.is_adj
insert(propses, parsed_alternating_segment.propses)
end
if is_adj == nil then
is_adj = this_is_adj
elseif this_is_adj ~= nil then
is_adj = is_adj and this_is_adj
end
end
end
if #parsed_segments > 1 then
track("multiple-segments")
end
return {
segments = parsed_segments,
loc = loc,
num = num,
gender = gender,
is_adj = is_adj,
propses = propses,
}
end
-- Combine each form in FORMS (a list of forms associated with a slot) with each
-- form in NEW_FORMS (either a single string for a single form, or a list of
-- forms) by concatenating EXISTING_FORM .. PREFIX .. NEW_FORM. Also combine
-- NOTES (a table specifying the footnotes associated with each existing form,
-- i.e. a map from form indices to lists of footnotes) with NEW_NOTES (new
-- footnotes associated with the new forms, in the same format as NOTES). Return
-- a pair NEW_FORMS, NEW_NOTES where either or both of FORMS and NOTES (but not
-- the sublists in NOTES) may be destructively modified to generate the return
-- values.
local function append_form(forms, notes, new_forms, new_notes, prefix)
if forms == nil then
return
end
new_forms = new_forms or ""
notes = notes or {}
new_notes = new_notes or {}
prefix = prefix or ""
if type(new_forms) == "table" and #new_forms == 1 then
new_forms = new_forms[1]
end
if type(new_forms) == "string" then
-- If there's only one new form, destructively modify the existing
-- forms and notes for this new form and its footnotes.
for i = 1, #forms do
forms[i] = forms[i] .. prefix .. new_forms
if new_notes[1] then
if not notes[i] then
notes[i] = new_notes[1]
else
local combined_notes = deep_copy(notes[i])
for _, note in ipairs(new_notes[1]) do
insert(combined_notes, note)
end
notes[i] = combined_notes
end
end
end
return forms, notes
else
-- If there are multiple new forms, we need to loop over all
-- combinations of new and old forms. In that case, use new tables
-- for the combined forms and notes.
local ret_forms = {}
local ret_notes = {}
for i=1, #forms do
for j=1, #new_forms do
insert(ret_forms, forms[i] .. prefix .. new_forms[j])
if new_notes[j] then
if not notes[i] then
-- We are constructing a linearized matrix of size
-- NI x NJ where J is in the inner loop. If I and J
-- are zero-based, the linear index of (I, J) is
-- I * NJ + J. However, we are one-based, so the
-- same formula won't work. Instead, we effectively
-- need to convert to zero-based indices, compute
-- the zero-based linear index, and then convert it
-- back to a one-based index, i.e.
--
-- (I - 1) * NJ + (J - 1) + 1
--
-- i.e. (I - 1) * NJ + J.
ret_notes[(i - 1) * #new_forms + j] = new_notes[j]
else
local combined_notes = deep_copy(notes[i])
for _, note in ipairs(new_notes[j]) do
insert(combined_notes, note)
end
ret_notes[(i - 1) * #new_forms + j] = combined_notes
end
end
end
end
return ret_forms, ret_notes
end
end
-- Destructively modify any forms in FORMS (a map from a slot to a form or a
-- list of forms) by converting sequences of ae, oe, Ae or Oe to the
-- appropriate ligatures.
local function apply_ligatures(forms, is_adj)
for slot in iter_slots(is_adj) do
if type(forms[slot]) == "string" then
forms[slot] = forms[slot]:gsub("[AaOo]e", ligatures)
elseif type(forms[slot]) == "table" then
for i = 1, #forms[slot] do
forms[slot][i] = forms[slot][i]:gsub("[AaOo]e", ligatures)
end
end
end
end
-- Modify any forms in FORMS (a map from a slot to a form or a list of forms) by
-- converting final m to optional n or m.
local function apply_sufn(forms, is_adj)
for slot in iter_slots(is_adj) do
if type(forms[slot]) == "string" then
if forms[slot]:sub(-1) == "m" then
forms[slot] = {forms[slot]:gsub("m$", "n"), forms[slot]}
end
elseif type(forms[slot]) == "table" then
-- See if there are any final m's.
local final_m
for i = 1, #forms[slot] do
if forms[slot][i]:sub(-1) == "m" then
final_m = true
break
end
end
if final_m then
local newval = {}
for i = 1, #forms[slot] do
if forms[slot][i]:sub(-1) == "m" then
insert(newval, (forms[slot][i]:gsub("m$", "n")))
end
insert(newval, forms[slot][i])
end
forms[slot] = newval
end
end
end
end
-- If NUM == "sg", copy the singular forms to the plural ones; vice-versa if
-- NUM == "pl". This should allow for the equivalent of plural
-- "alpha and omega" formed from two singular nouns, and for the equivalent of
-- plural "St. Vincent and the Grenadines" formed from a singular noun and a
-- plural noun. (These two examples actually occur in Russian, at least.)
local function propagate_number_restrictions(forms, num, is_adj)
if num == "sg" or num == "pl" then
for slot in iter_slots(is_adj) do
if slot:find(num, nil, true) then
local other_num_slot = num == "sg" and slot:gsub("sg", "pl") or slot:gsub("pl", "sg")
forms[other_num_slot] = type(forms[slot]) == "table" and deep_copy(forms[slot]) or forms[slot]
end
end
end
end
local function join_sentences(sentences, joiner)
-- Lowercase the first letter of all but the first sentence, and remove the
-- final period from all but the last sentence. Then join together with the
-- joiner (e.g. " and " or " or ").
-- FIXME: Should we join three or more as e.g. "foo, bar and baz"?
local sentences_to_join = {}
for i, sentence in ipairs(sentences) do
if i < #sentences then
sentence = sentence:gsub("%.$", "")
end
if i > 1 then
sentence = lcfirst(sentence)
end
insert(sentences_to_join, sentence)
end
return concat(sentences_to_join, joiner)
end
-- Construct the declension of a parsed segment run of the form returned by
-- parse_segment_run() or parse_segment_run_allowing_alternants(). Return value
-- is a table
-- {
-- forms = FORMS (keyed by slot, list of forms for that slot),
-- notes = NOTES (keyed by slot, map from form indices to lists of footnotes),
-- title = TITLE (list of titles for each segment in the run),
-- categories = CATEGORIES (combined categories for all segments),
-- }
local function decline_segment_run(parsed_run, pos, is_adj)
local declensions = {
-- For each possible slot (e.g. "abl_sg"), list of possible forms.
forms = {},
-- Keyed by slot (e.g. "abl_sg"). Value is a table indicating the footnotes
-- corresponding to the forms for that slot. Each such table maps indices
-- (the index of the corresponding form) to a list of one or more
-- footnotes.
notes = {},
title = {},
unattested = {},
subtitleses = {},
orig_titles = {},
categories = {},
footnotes = {},
-- May be set true if declining a 1-1 adjective
loc = false,
noneut = false,
nomf = false,
}
for slot in iter_slots(is_adj) do
declensions.forms[slot] = {""}
end
for i, seg in ipairs(parsed_run.segments) do
local decl = seg.decl
if decl then -- not an alternant, not a constant segment
seg.loc = parsed_run.loc
seg.num = seg.num or parsed_run.num
seg.gender = seg.gender or parsed_run.gender
local data, potential_lemma_slots
if seg.is_adj then
if not (m_adj_decl or get_m_adj_decl())[decl] then
error("Unrecognized declension '" .. decl .. "'")
end
potential_lemma_slots = potential_adj_lemma_slots
data = {
subtitles = {},
num = seg.num or "",
gender = seg.gender,
loc = seg.loc,
noneut = false,
nomf = false,
pos = is_adj and pos or "adjectives",
forms = {},
types = seg.types,
unattested = {},
categories = {},
notes = {},
}
(m_adj_decl or get_m_adj_decl())[decl](data, seg.args)
local apparent_decl = data.decl or decl
if data.loc then
declensions.loc = true
end
if data.noneut then
declensions.noneut = true
end
if data.nomf then
declensions.nomf = true
end
-- Construct title out of "original title" and subtitles.
if not data.title then
if decl == "irreg+" and apparent_decl ~= decl and #data.subtitles == 0 then
insert(data.subtitles, glossary_link("irregular"))
end
if declension_to_english[apparent_decl] then
local english = declension_to_english[apparent_decl]
data.title = "[[Appendix:Latin " .. english .. " declension|" .. english .. "-declension]]"
elseif apparent_decl == "irreg+" then
data.title = glossary_link("irregular")
elseif apparent_decl == "indecl+" or apparent_decl == "0+" then
data.title = glossary_link("indeclinable")
else
error("Internal error! Don't recognize adjective declension " .. apparent_decl)
end
data.title = data.title .. " " .. singularize(data.pos)
end
if data.types.sufn then
insert(data.subtitles, {"with", " ''m'' optionally → ''n'' in compounds"})
elseif data.types.not_sufn then
insert(data.subtitles, {"without", " ''m'' optionally → ''n'' in compounds"})
end
-- Record original title and subtitles for use in alternant title-constructing code.
insert(declensions.orig_titles, data.title)
if #data.subtitles > 0 then
local subtitles = {}
for _, subtitle in ipairs(data.subtitles) do
if type(subtitle) == "table" then
-- Occurs e.g. with ''idem'', ''quīdam''
insert(subtitles, concat(subtitle))
else
insert(subtitles, subtitle)
end
end
data.title = data.title .. " (" .. concat(subtitles, ", ") .. ")"
end
insert(declensions.subtitleses, data.subtitles)
else
if not (m_noun_decl or get_m_noun_decl())[decl] then
error("Unrecognized declension '" .. decl .. "'")
end
potential_lemma_slots = potential_noun_lemma_slots
data = {
subtitles = {},
num = seg.num or "",
loc = seg.loc,
pos = pos,
forms = {},
types = seg.types,
unattested = {},
categories = {},
notes = {},
}
(m_noun_decl or get_m_noun_decl())[decl](data, seg.args)
local apparent_decl = data.decl or decl
seg.props.headword_decl = apparent_decl
-- Construct title out of "original title" and subtitles.
if not data.title then
if decl == "irreg" and apparent_decl ~= decl and #data.subtitles == 0 then
insert(data.subtitles, glossary_link("irregular"))
end
if declension_to_english[apparent_decl] then
local english = declension_to_english[apparent_decl]
data.title = "[[Appendix:Latin " .. english .. " declension|" .. english .. "-declension]]"
elseif apparent_decl == "irreg" then
data.title = glossary_link("irregular")
elseif apparent_decl == "indecl" or apparent_decl == "0" or apparent_decl == "sgpl" then
data.title = glossary_link("indeclinable")
else
error("Internal error! Don't recognize noun declension " .. apparent_decl)
end
data.title = data.title .. " " .. singularize(data.pos)
end
if data.types.sufn then
insert(data.subtitles, {"with", " ''m'' optionally → ''n'' in compounds"})
elseif data.types.not_sufn then
insert(data.subtitles, {"without", " ''m'' optionally → ''n'' in compounds"})
end
-- Record original title and subtitles for use in alternant title-constructing code.
insert(declensions.orig_titles, data.title)
if #data.subtitles > 0 then
local subtitles = {}
for _, subtitle in ipairs(data.subtitles) do
if type(subtitle) == "table" then
-- Occurs e.g. with 1st-declension ''-ābus'' ending where
-- we want a common prefix to be extracted out if possible
-- in the alternant title-generating code.
insert(subtitles, concat(subtitle))
else
insert(subtitles, subtitle)
end
end
data.title = data.title .. " (" .. concat(subtitles, ", ") .. ")"
end
insert(declensions.subtitleses, data.subtitles)
end
-- Generate linked variants of slots that may be the lemma.
-- If the form is the same as the lemma (with links removed),
-- substitute the original lemma (with links included).
for _, slot in ipairs(potential_lemma_slots) do
local forms = data.forms[slot]
if forms then
local linked_forms = {}
if type(forms) ~= "table" then
forms = {forms}
end
for _, form in ipairs(forms) do
if form == seg.lemma then
insert(linked_forms, seg.orig_lemma)
else
insert(linked_forms, form)
end
end
data.forms["linked_" .. slot] = linked_forms
end
end
if seg.types.lig then
apply_ligatures(data.forms, is_adj)
end
if seg.types.sufn then
apply_sufn(data.forms, is_adj)
end
propagate_number_restrictions(data.forms, seg.num, is_adj)
for slot in iter_slots(is_adj) do
-- 1. Select the forms to append to the existing ones.
local new_forms
if is_adj then
if not seg.is_adj then
error("Can't decline noun '" .. seg.lemma .. "' when overall term is an adjective")
end
new_forms = data.forms[slot]
if not new_forms and slot:find("_[fn]$") then
new_forms = data.forms[slot:gsub("_[fn]$", "_m")]
end
elseif seg.is_adj then
if not seg.gender then
error("Declining modifying adjective " .. seg.lemma .. " but don't know gender of associated noun")
end
-- Select the appropriately gendered equivalent of the case/number
-- combination. Some adjectives won't have feminine or neuter
-- variants, though (e.g. 3-1 and 3-2 adjectives don't have a
-- distinct feminine), so in that case select the masculine.
new_forms = data.forms[slot .. "_" .. mw.ustring.lower(seg.gender)]
or data.forms[slot .. "_m"]
else
new_forms = data.forms[slot]
end
-- 2. Extract the new footnotes in the format we require, which is
-- different from the format passed in by the declension functions.
local new_notes = {}
if type(new_forms) == "string" and data.notes[slot .. "1"] then
new_notes[1] = {data.notes[slot .. "1"]}
elseif new_forms then
for j = 1, #new_forms do
if data.notes[slot .. j] then
new_notes[j] = {data.notes[slot .. j]}
end
end
end
-- 3. Append new forms and footnotes to the existing ones.
new_forms = normalize_form(new_forms)
if new_forms == nil then
declensions.forms[slot] = nil
declensions.notes[slot] = nil
else
declensions.forms[slot], declensions.notes[slot] = append_form(
declensions.forms[slot], declensions.notes[slot], new_forms,
new_notes, slot:find("linked", nil, true) and seg.orig_prefix or seg.prefix)
end
end
for slot, v in pairs(data.unattested) do
if v then
declensions.unattested[slot] = true
end
end
if not seg.types.nocat and (is_adj or not seg.is_adj) then
for _, cat in ipairs(data.categories) do
insert_if_not(declensions.categories, cat)
end
end
if data.footnote then
insert(declensions.footnotes, data.footnote)
end
if seg.prefix ~= "" and seg.prefix ~= "-" and seg.prefix ~= " " then
insert(declensions.title, glossary_link("indeclinable") .. " portion")
end
insert(declensions.title, data.title)
elseif seg.alternants then
local seg_declensions = nil
local seg_titles = {}
local seg_subtitleses = {}
local seg_stems_seen = {}
local seg_unattested = {}
local seg_categories = {}
local seg_footnotes = {}
-- If all alternants have exactly one non-constant segment and all are
-- of the same declension, we use special code that displays the
-- differences in the subtitles. Otherwise we use more general code
-- that displays the full title and subtitles of each segment,
-- separating segment combined titles by "and" and the segment-run
-- combined titles by "or".
local title_the_hard_way = false
local alternant_decl = nil
local alternant_decl_title = nil
for _, this_parsed_run in ipairs(seg.alternants) do
local num_non_constant_segments = 0
for _, segment in ipairs(this_parsed_run.segments) do
if segment.decl then
if not alternant_decl then
alternant_decl = segment.decl
elseif alternant_decl ~= segment.decl then
title_the_hard_way = true
num_non_constant_segments = 500
break
end
num_non_constant_segments = num_non_constant_segments + 1
end
end
if num_non_constant_segments ~= 1 then
title_the_hard_way = true
break
end
end
if not title_the_hard_way then
-- If using the special-purpose code, find the subtypes that are
-- not present in a given alternant but are present in at least
-- one other, and record "negative" variants of these subtypes
-- so that the declension-construction code can record subtitles
-- for these negative variants (so we can construct text like
-- "i-stem or imparisyllabic non-i-stem").
local subtypeses = {}
for _, this_parsed_run in ipairs(seg.alternants) do
for _, segment in ipairs(this_parsed_run.segments) do
if segment.decl then
insert(subtypeses, segment.types)
insert_if_not(seg_stems_seen, segment.stem2)
end
end
end
local union = set_union(subtypeses)
for _, this_parsed_run in ipairs(seg.alternants) do
for _, segment in ipairs(this_parsed_run.segments) do
if segment.decl then
local neg_subtypes = set_difference(union, segment.types)
for neg_subtype, _ in pairs(neg_subtypes) do
segment.types["not_" .. neg_subtype] = true
end
end
end
end
end
for _, this_parsed_run in ipairs(seg.alternants) do
this_parsed_run.loc = seg.loc
this_parsed_run.num = this_parsed_run.num or seg.num
this_parsed_run.gender = this_parsed_run.gender or seg.gender
local this_declensions = decline_segment_run(this_parsed_run, pos, is_adj)
if this_declensions.noneut then
declensions.noneut = true
end
if this_declensions.nomf then
declensions.nomf = true
end
-- If there's a number restriction on the segment run, blank
-- out the forms outside the restriction. This allows us to
-- e.g. construct heteroclites that decline one way in the
-- singular and a different way in the plural.
if this_parsed_run.num == "sg" or this_parsed_run.num == "pl" then
for slot in iter_slots(is_adj) do
if this_parsed_run.num == "sg" and slot:find("pl", nil, true) or
this_parsed_run.num == "pl" and slot:find("sg", nil, true) then
this_declensions.forms[slot] = {}
this_declensions.notes[slot] = nil
end
end
end
if not seg_declensions then
seg_declensions = this_declensions
else
for slot in iter_slots(is_adj) do
-- For a given slot, combine the existing and new forms.
-- We do this by checking to see whether a new form is
-- already present and not adding it if so; in the
-- process, we keep a map from indices in the new forms
-- to indices in the combined forms, for use in
-- combining footnotes below.
local curforms = seg_declensions.forms[slot] or {}
local newforms = this_declensions.forms[slot] or {}
local newform_index_to_new_index = {}
for newj, form in ipairs(newforms) do
local did_break = false
for j = 1, #curforms do
if curforms[j] == form then
newform_index_to_new_index[newj] = j
did_break = true
break
end
end
if not did_break then
insert(curforms, form)
newform_index_to_new_index[newj] = #curforms
end
end
seg_declensions.forms[slot] = curforms
-- Now combine the footnotes. Keep in mind that
-- each form may have its own set of footnotes, and
-- in some cases we didn't add a form from the new
-- list of forms because it already occurred in the
-- existing list of forms; in that case, we combine
-- footnotes from the two sources.
local curnotes = seg_declensions.notes[slot]
local newnotes = this_declensions.notes[slot]
if newnotes then
if not curnotes then
curnotes = {}
end
for index, notes in pairs(newnotes) do
local combined_index = newform_index_to_new_index[index]
if not curnotes[combined_index] then
curnotes[combined_index] = notes
else
local combined = mw.clone(curnotes[combined_index])
for _, note in ipairs(newnotes) do
insert_if_not(combined, note)
end
curnotes[combined_index] = combined
end
end
end
end
end
for slot, v in pairs(this_declensions.unattested) do
if v then
seg_unattested[slot] = true
end
end
for _, cat in ipairs(this_declensions.categories) do
insert_if_not(seg_categories, cat)
end
for _, footnote in ipairs(this_declensions.footnotes) do
insert_if_not(seg_footnotes, footnote)
end
insert_if_not(seg_titles, this_declensions.title)
for _, subtitles in ipairs(this_declensions.subtitleses) do
insert(seg_subtitleses, subtitles)
end
if not alternant_decl_title then
alternant_decl_title = this_declensions.orig_titles[1]
end
end
-- If overall run is singular, copy singular to plural, and
-- vice-versa. See propagate_number_restrictions() for rationale;
-- also, this should eliminate cases of empty forms, which will
-- cause the overall set of forms for that slot to be empty.
propagate_number_restrictions(seg_declensions.forms, parsed_run.num, is_adj)
for slot in iter_slots(is_adj) do
local new_forms = normalize_form(seg_declensions.forms[slot])
if new_forms == nil then
declensions.forms[slot] = nil
declensions.notes[slot] = nil
else
declensions.forms[slot], declensions.notes[slot] = append_form(
declensions.forms[slot], declensions.notes[slot],
new_forms, seg_declensions.notes[slot], nil)
end
end
for slot, v in pairs(seg_unattested) do
if v then
declensions.unattested[slot] = true
end
end
if is_adj or not seg.is_adj then
for _, cat in ipairs(seg_categories) do
insert_if_not(declensions.categories, cat)
end
end
for _, footnote in ipairs(seg_footnotes) do
insert_if_not(declensions.footnotes, footnote)
end
local title_to_insert
if title_the_hard_way then
title_to_insert = join_sentences(seg_titles, " or ")
else
-- Special-purpose title-generation code, for the common
-- situation where each alternant has single-segment runs and
-- all segments belong to the same declension.
--
-- 1. Find the initial subtitles common to all segments.
local first_subtitles = seg_subtitleses[1]
local num_common_subtitles = #first_subtitles
for j = 2, #seg_subtitleses do
local this_subtitles = seg_subtitleses[j]
for k = 1, num_common_subtitles do
if not deep_equals(first_subtitles[k], this_subtitles[k]) then
num_common_subtitles = k - 1
break
end
end
end
-- 2. Construct the portion of the text based on the common subtitles.
local common_subtitles = {}
for j = 1, num_common_subtitles do
if type(first_subtitles[j]) == "table" then
insert(common_subtitles, concat(first_subtitles[j]))
else
insert(common_subtitles, first_subtitles[j])
end
end
local common_subtitle_portion = concat(common_subtitles, ", ")
local non_common_subtitle_portion
-- 3. Special-case the situation where there's one non-common
-- subtitle in each segment and a common prefix or suffix to
-- all of them.
local common_prefix, common_suffix
for j = 1, #seg_subtitleses do
local this_subtitles = seg_subtitleses[j]
if #this_subtitles ~= num_common_subtitles + 1 or
type(this_subtitles[num_common_subtitles + 1]) ~= "table" or
#this_subtitles[num_common_subtitles + 1] ~= 2 then
break
end
if j == 1 then
common_prefix = this_subtitles[num_common_subtitles + 1][1]
common_suffix = this_subtitles[num_common_subtitles + 1][2]
else
local this_prefix = this_subtitles[num_common_subtitles + 1][1]
local this_suffix = this_subtitles[num_common_subtitles + 1][2]
if this_prefix ~= common_prefix then
common_prefix = nil
end
if this_suffix ~= common_suffix then
common_suffix = nil
end
if not common_prefix and not common_suffix then
break
end
end
end
if common_prefix or common_suffix then
if common_prefix and common_suffix then
error("Something is wrong, first non-common subtitle is actually common to all segments")
end
if common_prefix then
local non_common_parts = {}
for j = 1, #seg_subtitleses do
insert(non_common_parts, seg_subtitleses[j][num_common_subtitles + 1][2])
end
non_common_subtitle_portion = common_prefix .. concat(non_common_parts, " or ")
else
local non_common_parts = {}
for j = 1, #seg_subtitleses do
insert(non_common_parts, seg_subtitleses[j][num_common_subtitles + 1][1])
end
non_common_subtitle_portion = concat(non_common_parts, " or ") .. common_suffix
end
else
-- 4. Join the subtitles that differ from segment to segment.
-- Record whether there are any such differing subtitles.
-- If some segments have differing subtitles and others don't,
-- we use the text "otherwise" for the segments without
-- differing subtitles.
local saw_non_common_subtitles = false
local non_common_subtitles = {}
for j = 1, #seg_subtitleses do
local this_subtitles = seg_subtitleses[j]
local this_non_common_subtitles = {}
for k = num_common_subtitles + 1, #this_subtitles do
if type(this_subtitles[k]) == "table" then
insert(this_non_common_subtitles, concat(this_subtitles[k]))
else
insert(this_non_common_subtitles, this_subtitles[k])
end
end
if #this_non_common_subtitles > 0 then
insert(non_common_subtitles, concat(this_non_common_subtitles, ", "))
saw_non_common_subtitles = true
else
insert(non_common_subtitles, "otherwise")
end
end
non_common_subtitle_portion =
saw_non_common_subtitles and concat(non_common_subtitles, " or ") or ""
end
-- 5. Combine the common and non-common subtitle portions.
local subtitle_portions = {}
if common_subtitle_portion ~= "" then
insert(subtitle_portions, common_subtitle_portion)
end
if non_common_subtitle_portion ~= "" then
insert(subtitle_portions, non_common_subtitle_portion)
end
if #seg_stems_seen > 1 then
insert(subtitle_portions,
(number_to_english[#seg_stems_seen] or "" .. #seg_stems_seen) .. " different stems"
)
end
local subtitle_portion = concat(subtitle_portions, "; ")
if subtitle_portion ~= "" then
title_to_insert = alternant_decl_title .. " (" .. subtitle_portion .. ")"
else
title_to_insert = alternant_decl_title
end
end
-- Don't insert blank title (happens e.g. with "((ali))quis<irreg+>").
if title_to_insert ~= "" then
insert(declensions.title, title_to_insert)
end
else
for slot in iter_slots(is_adj) do
declensions.forms[slot], declensions.notes[slot] = append_form(
declensions.forms[slot], declensions.notes[slot],
slot:find("linked", nil, true) and seg.orig_prefix or seg.prefix)
end
insert(declensions.title, glossary_link("indeclinable") .. " portion")
end
end
-- First title is uppercase, remainder have an indefinite article, joined
-- using "with".
local titles = {}
for i, title in ipairs(declensions.title) do
if i == 1 then
insert(titles, ucfirst(title))
else
insert(titles, add_indefinite_article(title))
end
end
declensions.title = concat(titles, " with ")
return declensions
end
local function construct_title(args_title, declensions_title, generate_type, parsed_run)
if args_title then
declensions_title = args_title:gsub("<1>", "[[Appendix:Latin first declension|first declension]]")
declensions_title = declensions_title:gsub("<1&2>", "[[Appendix:Latin first declension|first]]/[[Appendix:Latin second declension|second declension]]")
declensions_title = declensions_title:gsub("<2>", "[[Appendix:Latin second declension|second declension]]")
declensions_title = declensions_title:gsub("<3>", "[[Appendix:Latin third declension|third declension]]")
declensions_title = declensions_title:gsub("<4>", "[[Appendix:Latin fourth declension|fourth declension]]")
declensions_title = declensions_title:gsub("<5>", "[[Appendix:Latin fifth declension|fifth declension]]")
if generate_type == "headword" then
declensions_title = lcfirst((declensions_title:gsub("%.$", "")))
else
declensions_title = ucfirst(declensions_title)
end
else
local post_text_parts = {}
if parsed_run.loc then
insert(post_text_parts, ", with locative")
end
-- FIXME: Hierosolyma has -a/-ōrum (2nd neut. pl. with sg. meaning) and -a/-ae (1st fem. sg.)
-- alternants, but because it has singular and plural forms overall, it's not made clear that
-- each alternant is restricted to one number.
if parsed_run.num == "sg" then
insert(post_text_parts, ", singular only")
elseif parsed_run.num == "pl" then
insert(post_text_parts, ", plural only")
end
local post_text = concat(post_text_parts)
if generate_type == "headword" then
declensions_title = lcfirst(declensions_title) .. post_text
else
declensions_title = ucfirst(declensions_title) .. post_text .. "."
end
end
return declensions_title
end
function export.do_generate_noun_forms(parent_args, pos, generate_type, def)
local params = {
[1] = {required = true, default = def or "aqua<1>"},
footnote = true,
title = true,
num = true,
json = {type = "boolean"},
}
for slot in iter_noun_slots() do
params[slot] = true
end
if generate_type == "headword" then
local list = {list = true}
local sublist = {sublist = "/"}
params.lemma = list
params.id = true
params.cat = list
params.m = sublist
params.f = sublist
params.n = sublist
params.adj = sublist
params.dim = sublist
params.aug = sublist
params.g = list
params.indecl = {type = "boolean"}
end
if pos == "numerals" then
params.type = true
end
local args = process_params(parent_args, params)
if args.title then
track("overriding-title")
end
local parsed_run = parse_segment_run_allowing_alternants(args[1])
parsed_run.loc = parsed_run.loc or not not (args.loc_sg or args.loc_pl)
parsed_run.num = args.num or parsed_run.num
local declensions = decline_segment_run(parsed_run, pos, false)
if not parsed_run.loc then
declensions.forms.loc_sg = nil
declensions.forms.loc_pl = nil
end
declensions.title = construct_title(args.title, declensions.title, generate_type, parsed_run)
local all_data = {
title = declensions.title,
footnotes = {},
num = parsed_run.num or "",
gender = parsed_run.gender,
propses = parsed_run.propses,
forms = declensions.forms,
unattested = declensions.unattested,
categories = declensions.categories,
notes = {},
user_specified = {},
overriding_lemma = args.lemma,
id = args.id,
pos = pos,
cat = args.cat,
indecl = args.indecl,
m = args.m,
f = args.f,
overriding_genders = args.g,
num_type = args["type"],
}
if generate_type ~= "bare" then
all_data.accel = {}
end
if args.footnote then
insert_if_not(all_data.footnotes, args.footnote)
end
for _, footnote in ipairs(declensions.footnotes) do
insert_if_not(all_data.footnotes, footnote)
end
for slot in iter_noun_slots() do
if declensions.notes[slot] then
for index, notes in pairs(declensions.notes[slot]) do
all_data.notes[slot .. index] = notes
end
end
end
process_noun_forms_and_overrides(all_data, args, generate_type)
if args.json then
return require(json_module).toJSON(all_data)
end
return all_data
end
function export.do_generate_adj_forms(parent_args, pos, generate_type, degree, def)
local boolean = {type = "boolean"}
local params = {
[1] = {required = true, default = def or "bonus"},
footnote = true,
title = true,
num = true,
noneut = boolean,
nomf = boolean,
json = boolean,
}
for slot in iter_adj_slots() do
params[slot] = true
end
for slot in iter_noun_slots(true) do
params[slot] = true
end
if generate_type == "headword" then
local list = {list = true}
local sublist = {sublist = "/"}
params.lemma = list
params.adv = sublist
params.id = true
params.cat = list
params.indecl = boolean
if degree == "comparative" or degree == "superlative" then
params.positive = sublist
end
if degree ~= "comparative" then
params.comp = sublist
end
if degree ~= "superlative" then
params.sup = sublist
end
end
local set_pos
if not pos then
params.pos = {set = {"adjective", "determiner", "participle", "pronoun"}, default = "adjective"}
set_pos = true
elseif pos == "numerals" then
params.type = true
end
local args = process_params(parent_args, params)
if set_pos then
pos = pluralize(args.pos)
end
for slot in iter_noun_slots(true) do
local arg = args[slot]
if arg ~= nil then
for i = 1, genders_n do
local slot_g = slot .. "_" .. genders[i]
local arg_g = args[slot_g]
if arg_g == nil then
args[slot_g] = arg
end
end
args[slot] = nil
end
end
if args.title then
track("overriding-title")
end
local segment_run = args[1]
if not segment_run:match("[<(]") then
-- If the segment run doesn't have any explicit declension specs or alternants,
-- add a default declension spec of <+> to it (or <0+> for indeclinable
-- adjectives). This allows the majority of adjectives to just specify
-- the lemma.
segment_run = segment_run .. (args.indecl and "<0+>" or "<+>")
end
local parsed_run = parse_segment_run_allowing_alternants(segment_run)
parsed_run.loc = parsed_run.loc or not not (
args.loc_sg_m or args.loc_sg_f or args.loc_sg_n or args.loc_pl_m or args.loc_pl_f or args.loc_pl_n
)
parsed_run.num = args.num or parsed_run.num
local declensions = decline_segment_run(parsed_run, pos, true)
if not parsed_run.loc then
declensions.forms.loc_sg_m = nil
declensions.forms.loc_sg_f = nil
declensions.forms.loc_sg_n = nil
declensions.forms.loc_pl_m = nil
declensions.forms.loc_pl_f = nil
declensions.forms.loc_pl_n = nil
end
declensions.title = construct_title(args.title, declensions.title, generate_type, parsed_run)
local all_data = {
title = declensions.title,
footnotes = {},
num = parsed_run.num or "",
propses = parsed_run.propses,
forms = declensions.forms,
unattested = declensions.unattested,
categories = declensions.categories,
notes = {},
user_specified = {},
accel = {},
loc = declensions.loc,
noneut = args.noneut or declensions.noneut,
nomf = args.nomf or declensions.nomf,
overriding_lemma = args.lemma,
positive = args.positive,
comp = args.comp,
sup = args.sup,
adv = args.adv,
id = args.id,
pos = pos,
cat = args.cat,
indecl = args.indecl,
num_type = args["type"],
}
if generate_type ~= "bare" then
all_data.accel = {}
end
if args.footnote then
insert_if_not(all_data.footnotes, args.footnote)
end
for _, footnote in ipairs(declensions.footnotes) do
insert_if_not(all_data.footnotes, footnote)
end
for slot in iter_adj_slots() do
if declensions.notes[slot] then
for index, notes in pairs(declensions.notes[slot]) do
all_data.notes[slot .. index] = notes
end
end
end
process_adj_forms_and_overrides(all_data, args, generate_type)
if args.json then
return require(json_module).toJSON(all_data)
end
return all_data
end
function export.show_noun(frame)
local parent_args = frame:getParent().args
local data = export.do_generate_noun_forms(parent_args, "nouns")
if type(data) == "string" then -- JSON
return data
end
show_forms(data, false)
local num = data.num
if num == "sg" then
return make_noun_table_sg(data)
elseif num == "pl" then
return make_noun_table_pl(data)
end
return make_noun_table(data)
end
function export.show_adj(frame)
local parent_args = frame:getParent().args
local data = export.do_generate_adj_forms(parent_args)
if type(data) == "string" then -- JSON
return data
end
partial_show_forms(data, true)
return make_adj_table(data)
end
return export
pwzratghl59s9zk2tey39zm8apzqz52
Modul:la-adj/data
828
68097
344385
204838
2026-05-25T23:53:05Z
Hakimi97
2668
Mengemas kini mengikut padanan Wikikamus bahasa Inggeris (semakan [[en:Special:Diff/90360664|90360664]])
344385
Scribunto
text/plain
local decl = {}
local en_utilities_module = "Module:en-utilities"
local la_utilities_module = "Module:la-utilities"
local table_deep_copy_module = "Module:table/deepCopy"
local table_empty_module = "Module:table/empty"
local table_insert_if_not_module = "Module:table/insertIfNot"
local require = require
local umatch = mw.ustring.match
local usub = mw.ustring.sub
local function add_form(...)
add_form = require(la_utilities_module).add_form
return add_form(...)
end
local function deep_copy(...)
deep_copy = require(table_deep_copy_module)
return deep_copy(...)
end
local function empty_table(...)
empty_table = require(table_empty_module)
return empty_table(...)
end
local function insert_if_not(...)
insert_if_not = require(table_insert_if_not_module)
return insert_if_not(...)
end
local function remove_forms(...)
remove_forms = require(la_utilities_module).remove_forms
return remove_forms(...)
end
local function singularize(...)
singularize = require(en_utilities_module).singularize
return singularize(...)
end
local function glossary_link(anchor, text)
text = text or anchor
return "[[Appendix:Glossary#" .. anchor .. "|" .. text .. "]]"
end
local function decl_link(english_declension, decl_text)
decl_text = decl_text or english_declension .. "-declension"
return "[[Appendix:Latin " .. english_declension .. " declension|" .. decl_text .. "]]"
end
decl["0+"] = function(data, args)
local forms, categories = data.forms, data.categories
local stem = args[1]
forms["nom_sg_m"] = stem
forms["nom_pl_m"] = stem
forms["gen_sg_m"] = stem
forms["gen_pl_m"] = stem
forms["dat_sg_m"] = stem
forms["dat_pl_m"] = stem
forms["acc_sg_m"] = stem
forms["acc_pl_m"] = stem
forms["abl_sg_m"] = stem
forms["abl_pl_m"] = stem
forms["voc_sg_m"] = stem
forms["voc_pl_m"] = stem
forms["loc_sg_m"] = stem
forms["loc_pl_m"] = stem
insert_if_not(categories, "Latin indeclinable " .. data.pos)
end
decl["1&2+"] = function(data, args)
local forms, types, pos, subtitles, categories = data.forms, data.types, data.pos, data.subtitles, data.categories
local stem = args[1]
local singpos, gender = singularize(pos), data.gender
if gender == "F" then
data.title = decl_link("first") .. " " .. singpos
elseif gender then
data.title = decl_link("second") .. " " .. singpos
else
data.title = decl_link("first", "first") .. "/" .. decl_link("second") .. " " .. singpos
end
local original
if types.er then
local final2 = stem:sub(-2)
if final2 == "er" then
insert_if_not(subtitles, "nominative masculine singular in ''-er''")
insert_if_not(categories, "Latin first and second declension "
.. pos .. " with nominative masculine singular in -er")
elseif final2 == "ur" then
insert_if_not(subtitles, "nominative masculine singular in ''-ur''")
insert_if_not(categories, "Latin first and second declension "
.. pos .. " with nominative masculine singular in -ur")
else
error("Unrecognized ''-r'' stem (doesn't end in ''-er'' or ''-ur''): " .. stem)
end
stem, original = args[2], stem
end
local us = "us"
local a_sf = "a"
local um = "um"
local ae_gsf = "ae"
local am = "am"
local a_macron = "ā"
local i_pl = stem .. "ī"
if types.greekA or types.greekE then
insert_if_not(subtitles, "Greek-type")
insert_if_not(categories, "Latin first and second declension " .. pos .. " with Greek declension")
if types.greekA then
us = "os"
um = "on"
am = "ān"
else
us = "os"
a_sf = "ē"
um = "on"
ae_gsf = "ēs"
am = "ēn"
a_macron = "ē"
end
i_pl = {i_pl, stem .. "oe"} -- FIXME: add .oe spec.
end
forms["nom_sg_m"] = original or (stem .. us)
forms["nom_sg_f"] = stem .. a_sf
forms["nom_sg_n"] = stem .. um
forms["nom_pl_m"] = i_pl
forms["nom_pl_f"] = stem .. "ae"
forms["nom_pl_n"] = stem .. "a"
forms["gen_sg_m"] = stem .. "ī"
forms["gen_sg_f"] = stem .. ae_gsf
forms["gen_sg_n"] = stem .. "ī"
forms["gen_pl_m"] = stem .. "ōrum"
forms["gen_pl_f"] = stem .. "ārum"
forms["gen_pl_n"] = stem .. "ōrum"
forms["dat_sg_m"] = stem .. "ō"
forms["dat_sg_f"] = stem .. "ae"
forms["dat_sg_n"] = stem .. "ō"
forms["dat_pl_m"] = stem .. "īs"
forms["dat_pl_f"] = stem .. "īs"
forms["dat_pl_n"] = stem .. "īs"
forms["acc_sg_m"] = stem .. um
forms["acc_sg_f"] = stem .. am
forms["acc_sg_n"] = stem .. um
forms["acc_pl_m"] = stem .. "ōs"
forms["acc_pl_f"] = stem .. "ās"
forms["acc_pl_n"] = stem .. "a"
forms["abl_sg_m"] = stem .. "ō"
forms["abl_sg_f"] = stem .. a_macron
forms["abl_sg_n"] = stem .. "ō"
forms["abl_pl_m"] = stem .. "īs"
forms["abl_pl_f"] = stem .. "īs"
forms["abl_pl_n"] = stem .. "īs"
forms["voc_sg_m"] = original or (stem .. "e")
forms["voc_sg_f"] = stem .. a_sf
forms["voc_sg_n"] = stem .. um
forms["voc_pl_m"] = i_pl
forms["voc_pl_f"] = stem .. "ae"
forms["voc_pl_n"] = stem .. "a"
if types.ius then
insert_if_not(subtitles, "pronominal declension")
--insert_if_not(subtitles, "with genitive singular in ''-ī̆us'' and dative singular in ''-ī''")
insert_if_not(categories, "Latin first and second declension " .. pos .. " with genitive singular in -ī̆us")
forms["gen_sg_m"] = stem .. "ī̆us"
forms["gen_sg_f"] = stem .. "ī̆us"
forms["gen_sg_n"] = stem .. "ī̆us"
forms["dat_sg_m"] = stem .. "ī"
forms["dat_sg_f"] = stem .. "ī"
forms["dat_sg_n"] = stem .. "ī"
elseif types.not_ius then
insert_if_not(subtitles, "non-pronominal declension")
--insert_if_not(subtitles, "with normal genitive and dative singular")
end
if stem == "me" then
forms["voc_sg_m"] = "mī"
end
if types.ic then
insert_if_not(subtitles, "''hic''-type")
--insert_if_not(subtitles, "with genitive singular ending in ''-ius'' and dative singular ending in ''-ic''")
local oc = "oc"
local oc_macron = "ōc"
if stem == "ill" then
oc = "uc"
oc_macron = "ūc"
end
forms["nom_sg_m"] = stem .. "ic"
forms["nom_sg_f"] = stem .. "aec"
forms["nom_sg_n"] = stem .. oc
forms["nom_pl_n"] = stem .. "aec"
forms["gen_sg_m"] = stem .. "uius"
forms["gen_sg_f"] = stem .. "uius"
forms["gen_sg_n"] = stem .. "uius"
forms["dat_sg_m"] = stem .. "uic"
forms["dat_sg_f"] = stem .. "uic"
forms["dat_sg_n"] = stem .. "uic"
forms["acc_sg_m"] = stem .. "unc"
forms["acc_sg_f"] = stem .. "anc"
forms["acc_sg_n"] = stem .. oc
forms["acc_pl_n"] = stem .. "aec"
forms["abl_sg_m"] = stem .. "ōc"
forms["abl_sg_f"] = stem .. "āc"
forms["abl_sg_n"] = stem .. oc_macron
forms["voc_sg_m"] = "-"
forms["voc_sg_f"] = "-"
forms["voc_sg_n"] = "-"
forms["voc_pl_m"] = "-"
forms["voc_pl_f"] = "-"
forms["voc_pl_n"] = "-"
end
if types.distr then
if stem:sub(-1) == "n" then
insert_if_not(subtitles, "distributive, normally plural-only; short genitive plurals in ''-num'' preferred")
forms["gen_pl_m"] = {stem .. "um", stem .. "ōrum"}
forms["gen_pl_f"] = {stem .. "um", stem .. "ārum"}
forms["gen_pl_n"] = {stem .. "um", stem .. "ōrum"}
else
error("Unrecognized distributive numeral stem (doesn't end in ''n''): " .. stem)
end
original = stem
stem = args[2]
end
forms["loc_sg_m"] = deep_copy(forms["gen_sg_m"])
forms["loc_sg_f"] = deep_copy(forms["gen_sg_f"])
forms["loc_sg_n"] = deep_copy(forms["gen_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_f"] = deep_copy(forms["abl_pl_f"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin first and second declension " .. pos)
end
decl["1-1+"] = function(data, args)
local forms, pos, subtitles, categories = data.forms, data.pos, data.subtitles, data.categories
local stem = args[1]
data.title = decl_link("first") .. " one-termination " .. singularize(pos)
forms["nom_sg_m"] = stem .. "a"
forms["nom_pl_m"] = stem .. "ae"
forms["nom_pl_n"] = stem .. "a"
forms["gen_sg_m"] = stem .. "ae"
forms["gen_pl_m"] = stem .. "ārum"
forms["dat_sg_m"] = stem .. "ae"
forms["dat_pl_m"] = stem .. "īs"
forms["acc_sg_m"] = stem .. "am"
forms["acc_sg_n"] = stem .. "a"
forms["acc_pl_m"] = stem .. "ās"
forms["acc_pl_n"] = stem .. "a"
forms["abl_sg_m"] = stem .. "ā"
forms["abl_pl_m"] = stem .. "īs"
forms["voc_sg_m"] = stem .. "a"
forms["voc_pl_m"] = stem .. "ae"
forms["voc_pl_n"] = stem .. "a"
forms["loc_sg_m"] = deep_copy(forms["gen_sg_m"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
insert_if_not(categories, "Latin first declension " .. data.pos)
end
decl["2-2+"] = function(data, args)
local forms, types, pos, subtitles, categories = data.forms, data.types, data.pos, data.subtitles, data.categories
local stem = args[1]
data.title = decl_link("second") .. " two-termination " .. singularize(pos)
local us = "us"
local um = "um"
local i_pl = stem .. "ī"
if types.greek then
insert_if_not(subtitles, "Greek-type")
insert_if_not(categories, "Latin second declension " .. pos .. " with Greek declension")
us = "os"
um = "on"
i_pl = {i_pl, stem .. "oe"} -- FIXME: add .oe spec.
end
forms["nom_sg_m"] = stem .. us
forms["nom_sg_n"] = stem .. um
forms["nom_pl_m"] = i_pl
forms["nom_pl_n"] = stem .. "a"
forms["gen_sg_m"] = stem .. "ī"
forms["gen_sg_n"] = stem .. "ī"
forms["gen_pl_m"] = stem .. "ōrum"
forms["gen_pl_n"] = stem .. "ōrum"
forms["dat_sg_m"] = stem .. "ō"
forms["dat_sg_n"] = stem .. "ō"
forms["dat_pl_m"] = stem .. "īs"
forms["dat_pl_n"] = stem .. "īs"
forms["acc_sg_m"] = stem .. um
forms["acc_sg_n"] = stem .. um
forms["acc_pl_m"] = stem .. "ōs"
forms["acc_pl_n"] = stem .. "a"
forms["abl_sg_m"] = stem .. "ō"
forms["abl_sg_n"] = stem .. "ō"
forms["abl_pl_m"] = stem .. "īs"
forms["abl_pl_n"] = stem .. "īs"
forms["voc_sg_m"] = stem .. "e"
forms["voc_sg_n"] = stem .. um
forms["voc_pl_m"] = i_pl
forms["voc_pl_n"] = stem .. "a"
forms["loc_sg_m"] = deep_copy(forms["gen_sg_m"])
forms["loc_sg_n"] = deep_copy(forms["gen_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin second declension " .. pos)
end
local function abl_i_e(...)
local function update_slot(forms, slot, f, do_copy)
if not forms[slot] then
return do_copy
elseif do_copy then
f = deep_copy(f)
end
forms[slot] = f
return true
end
function abl_i_e(stem, forms, types)
local f, do_copy
if types["abl_e_i"] then
f = {stem .. "e", stem .. "ī"}
elseif types["abl_i_e"] then
f = {stem .. "ī", stem .. "e"}
else
return
end
do_copy = update_slot(forms, "abl_sg_m", f, do_copy)
do_copy = update_slot(forms, "abl_sg_f", f, do_copy)
-- Neuter doesn't take -e with i-stems.
if not types.I then
update_slot(forms, "abl_sg_n", f, do_copy)
end
end
return abl_i_e(...)
end
decl["3-1+"] = function(data, args)
local forms, types, pos, subtitles, notes, categories = data.forms, data.types, data.pos, data.subtitles, data.notes, data.categories
local stem1, stem2 = args[1], args[2]
local singpos = singularize(pos)
if data.gender then
data.title = decl_link("third") .. " " .. singpos
else
data.title = decl_link("third") .. " one-termination " .. singpos
end
forms["nom_sg_m"] = stem1
forms["nom_sg_n"] = stem1
forms["nom_pl_m"] = stem2 .. "ēs"
forms["nom_pl_n"] = stem2 .. "ia"
forms["gen_sg_m"] = stem2 .. "is"
forms["gen_sg_n"] = stem2 .. "is"
forms["gen_pl_m"] = stem2 .. "ium"
forms["gen_pl_n"] = stem2 .. "ium"
forms["dat_sg_m"] = stem2 .. "ī"
forms["dat_sg_n"] = stem2 .. "ī"
forms["dat_pl_m"] = stem2 .. "ibus"
forms["dat_pl_n"] = stem2 .. "ibus"
forms["acc_sg_m"] = stem2 .. "em"
forms["acc_sg_n"] = stem1
forms["acc_pl_m"] = {stem2 .. "īs", stem2 .. "ēs"}
forms["acc_pl_n"] = stem2 .. "ia"
forms["abl_sg_m"] = {stem2 .. "ī", stem2 .. "e"}
forms["abl_sg_n"] = {stem2 .. "ī", stem2 .. "e"}
forms["abl_pl_m"] = stem2 .. "ibus"
forms["abl_pl_n"] = stem2 .. "ibus"
forms["voc_sg_m"] = stem1
forms["voc_sg_n"] = stem1
forms["voc_pl_m"] = stem2 .. "ēs"
forms["voc_pl_n"] = stem2 .. "ia"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
if types.par then
insert_if_not(subtitles, "non-i-stem")
forms["nom_pl_n"] = stem2 .. "a"
forms["gen_pl_m"] = stem2 .. "um"
forms["gen_pl_n"] = stem2 .. "um"
forms["abl_sg_m"] = stem2 .. "e"
forms["abl_sg_n"] = stem2 .. "e"
forms["loc_sg_m"] = {stem2 .. "ī", stem2 .. "e"} -- Really?
forms["loc_sg_n"] = {stem2 .. "ī", stem2 .. "e"} -- Why does this happen?
forms["acc_pl_n"] = stem2 .. "a"
forms["voc_pl_n"] = stem2 .. "a"
elseif types.not_par then
insert_if_not(subtitles, "i-stem")
end
local es_base = stem1:match("^(.-)ēs$")
if es_base and es_base == stem2 then
if types.greek then
local note1 = "It is unknown whether adjectives of this type would use i-stem or consonant-stem endings in Classical Latin: the relevant forms are not attested. Depending on the word, either ending or both may be attested in New Latin."
forms["nom_sg_n"] = stem2 .. "es"
forms["acc_sg_n"] = stem2 .. "es"
forms["voc_sg_n"] = stem2 .. "es"
forms["nom_pl_n"] = {stem2 .. "a", stem2 .. "ia"}
notes["nom_pl_n2"] = note1
forms["acc_pl_n"] = {stem2 .. "a", stem2 .. "ia"}
notes["acc_pl_n2"] = note1
forms["voc_pl_n"] = {stem2 .. "a", stem2 .. "ia"}
notes["voc_pl_n2"] = note1
forms["abl_sg_m"] = {stem2 .. "e", stem2 .. "ī"}
notes["abl_sg_m2"] = note1
forms["abl_sg_n"] = {stem2 .. "e", stem2 .. "ī"}
notes["abl_sg_n2"] = note1
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
notes["loc_sg_m2"] = note1
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
notes["loc_sg_n2"] = note1
forms["gen_pl_m"] = {stem2 .. "um", stem2 .. "ium"}
notes["gen_pl_m2"] = note1
forms["gen_pl_n"] = {stem2 .. "um", stem2 .. "ium"}
notes["gen_pl_n2"] = note1
insert_if_not(subtitles, "Greek-type")
elseif types.not_greek then
insert_if_not(subtitles, "non-Greek-type")
end
end
insert_if_not(categories, "Latin third declension " .. pos)
insert_if_not(categories, "Latin third declension " .. pos .. " of one termination")
end
decl["3-def+"] = function(data, args)
local forms, types, pos, subtitles, notes, categories = data.forms, data.types, data.pos, data.subtitles, data.notes, data.categories
local stem1, stem2 = args[1], args[2]
local singpos = singularize(pos)
if data.gender then
data.title = decl_link("third") .. " " .. singpos
else
data.title = decl_link("third") .. " defective " .. singpos
end
forms["nom_sg_m"] = stem1
forms["nom_sg_n"] = stem1
forms["nom_pl_m"] = stem2 .. "ēs"
forms["nom_pl_n"] = stem2 .. "ia"
forms["gen_sg_m"] = stem2 .. "is"
forms["gen_sg_n"] = stem2 .. "is"
forms["gen_pl_m"] = stem2 .. "ium"
forms["gen_pl_n"] = stem2 .. "ium"
forms["dat_sg_m"] = stem2 .. "ī"
forms["dat_sg_n"] = stem2 .. "ī"
forms["dat_pl_m"] = stem2 .. "ibus"
forms["dat_pl_n"] = stem2 .. "ibus"
forms["acc_sg_m"] = stem2 .. "em"
forms["acc_sg_n"] = stem1
forms["acc_pl_m"] = stem2 .. "ēs"
forms["acc_pl_n"] = stem2 .. "ia"
forms["abl_sg_m"] = stem2 .. "ī"
forms["abl_sg_n"] = stem2 .. "ī"
forms["abl_pl_m"] = stem2 .. "ibus"
forms["abl_pl_n"] = stem2 .. "ibus"
forms["voc_sg_m"] = stem1
forms["voc_sg_n"] = stem1
forms["voc_pl_m"] = stem2 .. "ēs"
forms["voc_pl_n"] = stem2 .. "ia"
if types.tor then
data.title = decl_link("third") .. " masculine-only " .. singpos
insert_if_not(subtitles, "non-i-stem")
remove_forms(forms, {"_f$", "_n$"})
forms["nom_sg_m"] = stem1
forms["gen_sg_m"] = stem2 .. "is"
forms["dat_sg_m"] = stem2 .. "ī"
forms["acc_sg_m"] = stem2 .. "em"
forms["abl_sg_m"] = stem2 .. "e"
forms["voc_sg_m"] = stem1
forms["nom_pl_m"] = stem2 .. "ēs"
forms["gen_pl_m"] = stem2 .. "um"
forms["dat_pl_m"] = stem2 .. "ibus"
forms["acc_pl_m"] = stem2 .. "ēs"
forms["abl_pl_m"] = stem2 .. "ibus"
forms["voc_pl_m"] = stem2 .. "ēs"
insert_if_not(categories, "Latin third declension masculine-only adjectives")
end
if types.trix then
insert_if_not(subtitles, "feminine-only when singular, feminine or neuter when plural")
remove_forms(forms, {"_m$", "sg_n$"})
forms["nom_sg_f"] = stem1
forms["gen_sg_f"] = stem2 .. "is"
forms["dat_sg_f"] = stem2 .. "ī"
forms["acc_sg_f"] = stem2 .. "em"
forms["abl_sg_f"] = {stem2 .. "e", stem2 .. "ī"}
forms["voc_sg_f"] = stem1
forms["nom_pl_f"] = stem2 .. "ēs"
forms["gen_pl_f"] = stem2 .. "ium"
forms["dat_pl_f"] = stem2 .. "ibus"
forms["acc_pl_f"] = stem2 .. "ēs"
forms["abl_pl_f"] = stem2 .. "ibus"
forms["voc_pl_f"] = stem2 .. "ēs"
insert_if_not(categories, "Latin third declension feminine- and neuter-only adjectives")
end
if types.trixf then
data.title = decl_link("third") .. " feminine-only " .. singpos
remove_forms(forms, {"_m$", "_n$"})
forms["nom_sg_f"] = stem1
forms["gen_sg_f"] = stem2 .. "is"
forms["dat_sg_f"] = stem2 .. "ī"
forms["acc_sg_f"] = stem2 .. "em"
forms["abl_sg_f"] = {stem2 .. "e", stem2 .. "ī"}
forms["voc_sg_f"] = stem1
forms["nom_pl_f"] = stem2 .. "ēs"
forms["gen_pl_f"] = stem2 .. "ium"
forms["dat_pl_f"] = stem2 .. "ibus"
forms["acc_pl_f"] = stem2 .. "ēs"
forms["abl_pl_f"] = stem2 .. "ibus"
forms["voc_pl_f"] = stem2 .. "ēs"
insert_if_not(categories, "Latin third declension feminine-only adjectives")
end
if types.idis then
data.title = decl_link("third") .. " feminine-only " .. singpos
insert_if_not(subtitles, "non-i-stem")
remove_forms(forms, {"_m$", "_n$"})
forms["nom_sg_f"] = stem1
forms["gen_sg_f"] = {stem2 .. "is", stem2 .. "os"}
forms["dat_sg_f"] = stem2 .. "ī"
forms["acc_sg_f"] = {stem2 .. "em", stem2 .. "a"}
forms["abl_sg_f"] = stem2 .. "e"
forms["voc_sg_f"] = stem1
forms["nom_pl_f"] = {stem2 .. "ēs", stem2 .. "es"}
forms["gen_pl_f"] = stem2 .. "um"
forms["dat_pl_f"] = stem2 .. "ibus"
forms["acc_pl_f"] = {stem2 .. "ēs", stem2 .. "as"}
forms["abl_pl_f"] = stem2 .. "ibus"
forms["voc_pl_f"] = {stem2 .. "ēs", stem2 .. "es"}
insert_if_not(categories, "Latin third declension feminine-only adjectives")
end
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_sg_f"] = deep_copy(forms["abl_sg_f"])
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_f"] = deep_copy(forms["abl_pl_f"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin third declension " .. pos)
end
decl["3-C+"] = function(data, args)
local forms, types, pos, categories = data.forms, data.types, data.pos, data.categories
local stem1 = args[1]
local stem2 = stem1 .. "ōr"
data.title = decl_link("third") .. " comparative " .. singularize(pos)
forms["nom_sg_m"] = stem1 .. "or"
forms["nom_sg_n"] = stem1 .. "us"
forms["nom_pl_m"] = stem2 .. "ēs"
forms["nom_pl_n"] = stem2 .. "a"
forms["gen_sg_m"] = stem2 .. "is"
forms["gen_sg_n"] = stem2 .. "is"
forms["gen_pl_m"] = stem2 .. "um"
forms["gen_pl_n"] = stem2 .. "um"
forms["dat_sg_m"] = stem2 .. "ī"
forms["dat_sg_n"] = stem2 .. "ī"
forms["dat_pl_m"] = stem2 .. "ibus"
forms["dat_pl_n"] = stem2 .. "ibus"
forms["acc_sg_m"] = stem2 .. "em"
forms["acc_sg_n"] = stem1 .. "us"
forms["acc_pl_m"] = {stem2 .. "ēs", stem2 .. "īs"}
forms["acc_pl_n"] = stem2 .. "a"
forms["abl_sg_m"] = stem2 .. "ī"
forms["abl_sg_n"] = stem2 .. "ī"
forms["abl_pl_m"] = stem2 .. "ibus"
forms["abl_pl_n"] = stem2 .. "ibus"
abl_i_e(stem2, forms, types)
forms["voc_sg_m"] = stem1 .. "or"
forms["voc_sg_n"] = stem1 .. "us"
forms["voc_pl_m"] = stem2 .. "ēs"
forms["voc_pl_n"] = stem2 .. "a"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin third declension " .. pos)
insert_if_not(categories, "Latin comparative adjectives")
end
decl["3-P+"] = function(data, args)
local forms, notes = data.forms, data.notes
local stem2 = args[2]
decl["3-1+"](data, args)
data.title = decl_link("third") .. " participle"
local note1 = "When used purely as an adjective."
forms["abl_sg_m"] = {stem2 .. "e", stem2 .. "ī"}
notes["abl_sg_m2"] = note1
forms["abl_sg_n"] = {stem2 .. "e", stem2 .. "ī"}
notes["abl_sg_n2"] = note1
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
notes["loc_sg_m2"] = note1
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
notes["loc_sg_n2"] = note1
forms["acc_pl_m"] = {stem2 .. "ēs", stem2 .. "īs"}
end
decl["3-2+"] = function(data, args)
local forms, types, pos, categories = data.forms, data.types, data.pos, data.categories
local stem = args[1]
local singpos = singularize(pos)
if data.gender then
data.title = decl_link("third") .. " " .. singpos
else
data.title = decl_link("third") .. " two-termination " .. singpos
end
forms["nom_sg_m"] = stem .. "is"
forms["nom_sg_n"] = stem .. "e"
forms["nom_pl_m"] = stem .. "ēs"
forms["nom_pl_n"] = stem .. "ia"
forms["gen_sg_m"] = stem .. "is"
forms["gen_sg_n"] = stem .. "is"
forms["gen_pl_m"] = stem .. "ium"
forms["gen_pl_n"] = stem .. "ium"
forms["dat_sg_m"] = stem .. "ī"
forms["dat_sg_n"] = stem .. "ī"
forms["dat_pl_m"] = stem .. "ibus"
forms["dat_pl_n"] = stem .. "ibus"
forms["acc_sg_m"] = stem .. "em"
forms["acc_sg_n"] = stem .. "e"
forms["acc_pl_m"] = {stem .. "īs", stem .. "ēs"}
forms["acc_pl_n"] = stem .. "ia"
forms["abl_sg_m"] = stem .. "ī"
forms["abl_sg_n"] = stem .. "ī"
forms["abl_pl_m"] = stem .. "ibus"
forms["abl_pl_n"] = stem .. "ibus"
-- abl_i_e(stem, forms, types) -- enable once [[Module:la-nominal]] has ben updated
forms["voc_sg_m"] = stem .. "is"
forms["voc_sg_n"] = stem .. "e"
forms["voc_pl_m"] = stem .. "ēs"
forms["voc_pl_n"] = stem .. "ia"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin third declension " .. pos)
insert_if_not(categories, "Latin third declension " .. pos .. " of two terminations")
end
decl["3-3+"] = function(data, args)
local forms, types, pos, categories = data.forms, data.types, data.pos, data.categories
local stem1, stem2 = args[1], args[2]
local singpos = singularize(pos)
if data.gender then
data.title = decl_link("third") .. " " .. singpos
else
data.title = decl_link("third") .. " three-termination " .. singpos
end
forms["nom_sg_m"] = stem1
forms["nom_sg_f"] = stem2 .. "is"
forms["nom_sg_n"] = stem2 .. "e"
forms["nom_pl_m"] = stem2 .. "ēs"
forms["nom_pl_f"] = stem2 .. "ēs"
forms["nom_pl_n"] = stem2 .. "ia"
forms["gen_sg_m"] = stem2 .. "is"
forms["gen_sg_f"] = stem2 .. "is"
forms["gen_sg_n"] = stem2 .. "is"
forms["gen_pl_m"] = stem2 .. "ium"
forms["gen_pl_f"] = stem2 .. "ium"
forms["gen_pl_n"] = stem2 .. "ium"
forms["dat_sg_m"] = stem2 .. "ī"
forms["dat_sg_f"] = stem2 .. "ī"
forms["dat_sg_n"] = stem2 .. "ī"
forms["dat_pl_m"] = stem2 .. "ibus"
forms["dat_pl_f"] = stem2 .. "ibus"
forms["dat_pl_n"] = stem2 .. "ibus"
forms["acc_sg_m"] = stem2 .. "em"
forms["acc_sg_f"] = stem2 .. "em"
forms["acc_sg_n"] = stem2 .. "e"
forms["acc_pl_m"] = {stem2 .. "īs", stem2 .. "ēs"}
forms["acc_pl_f"] = {stem2 .. "īs", stem2 .. "ēs"}
forms["acc_pl_n"] = stem2 .. "ia"
forms["abl_sg_m"] = stem2 .. "ī"
forms["abl_sg_f"] = stem2 .. "ī"
forms["abl_sg_n"] = stem2 .. "ī"
forms["abl_pl_m"] = stem2 .. "ibus"
forms["abl_pl_f"] = stem2 .. "ibus"
forms["abl_pl_n"] = stem2 .. "ibus"
-- abl_i_e(stem2, forms, types) -- enable once [[Module:la-nominal]] has ben updated
forms["voc_sg_m"] = stem1
forms["voc_sg_f"] = stem2 .. "is"
forms["voc_sg_n"] = stem2 .. "e"
forms["voc_pl_m"] = stem2 .. "ēs"
forms["voc_pl_f"] = stem2 .. "ēs"
forms["voc_pl_n"] = stem2 .. "ia"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_sg_f"] = deep_copy(forms["abl_sg_f"])
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_f"] = deep_copy(forms["abl_pl_f"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin third declension " .. pos)
insert_if_not(categories, "Latin third declension " .. pos .. " of three terminations")
end
decl["indecl+"] = function(data, args)
local forms, subtitles, categories = data.forms, data.subtitles, data.categories
local stem = args[1]
insert_if_not(subtitles, "used only in the nominative and accusative")
forms["nom_sg_m"] = stem
forms["nom_pl_m"] = "-"
forms["gen_sg_m"] = "-"
forms["gen_pl_m"] = "-"
forms["dat_sg_m"] = "-"
forms["dat_pl_m"] = "-"
forms["acc_sg_m"] = stem
forms["acc_pl_m"] = "-"
forms["abl_sg_m"] = "-"
forms["abl_pl_m"] = "-"
forms["voc_sg_m"] = "-"
forms["voc_pl_m"] = "-"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
insert_if_not(categories, "Latin indeclinable " .. data.pos)
end
decl["irreg+"] = function(data,args)
local forms, types, pos, notes, categories = data.forms, data.types, data.pos, data.notes, data.categories
local arg1 = args[1]
if arg1 == "duo" or arg1 == "ambō" then
local stem = usub(arg1, 1, -2)
data.title = stem == "amb" and glossary_link("irregular") .. " adjective" or "numeral"
data.num = "pl"
local stem_with_o = stem .. (stem == "amb" and "ō" or "o")
local note1 = "''[[duom#Latin|duom]]'' in Old Latin."
forms["nom_pl_m"] = stem_with_o
forms["nom_pl_f"] = stem .. "ae"
forms["nom_pl_n"] = stem_with_o
forms["gen_pl_m"] = stem .. "ōrum"
forms["gen_pl_f"] = stem .. "ārum"
forms["gen_pl_n"] = stem .. "ōrum"
forms["dat_pl_m"] = stem .. "ōbus"
forms["dat_pl_f"] = stem .. "ābus"
forms["dat_pl_n"] = stem .. "ōbus"
forms["acc_pl_m"] = {stem .. "ōs", stem_with_o}
forms["acc_pl_f"] = stem .. "ās"
forms["acc_pl_n"] = stem_with_o
forms["abl_pl_m"] = stem .. "ōbus"
forms["abl_pl_f"] = stem .. "ābus"
forms["abl_pl_n"] = stem .. "ōbus"
forms["voc_pl_m"] = stem_with_o
forms["voc_pl_f"] = stem .. "ae"
forms["voc_pl_n"] = stem_with_o
if stem == "du" then
forms["gen_pl_m"] = {forms["gen_pl_m"], "duum"}
notes["gen_pl_m2"] = note1
forms["gen_pl_n"] = {forms["gen_pl_n"], "duum"}
notes["gen_pl_n2"] = note1
end
elseif arg1:sub(-6) == "mīlle" then
data.title = "semi-" .. glossary_link("indeclinable") .. " numeral"
local stem = arg1:sub(1, -3)
forms["nom_sg_m"] = stem .. "le"
forms["nom_pl_m"] = {stem .. "ia", stem .. "lia"}
forms["gen_sg_m"] = stem .. "le"
forms["gen_pl_m"] = {stem .. "ium", stem .. "lium"}
forms["dat_sg_m"] = stem .. "le"
forms["dat_pl_m"] = {stem .. "ibus", stem .. "libus"}
forms["acc_sg_m"] = stem .. "le"
forms["acc_pl_m"] = {stem .. "ia", stem .. "lia"}
forms["abl_sg_m"] = stem .. "le"
forms["abl_pl_m"] = {stem .. "ibus", stem .. "libus"}
forms["voc_sg_m"] = stem .. "le"
forms["voc_pl_m"] = {stem .. "ia", stem .. "lia"}
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
elseif arg1 == "ille" or arg1 == "iste" or arg1 == "ipse" or arg1 == "olle" then
local stem = arg1:sub(1, -2)
types.ius = true
decl["1&2+"](data, {stem})
data.title = glossary_link("demonstrative") .. " " .. singularize(data.pos)
forms["nom_sg_m"] = arg1
if arg1 == "ipse" then
local note1 = "Medieval Latin."
add_form(forms, "nom_sg_n", stem, "ud")
notes["nom_sg_n2"] = note1
add_form(forms, "acc_sg_n", stem, "ud")
notes["acc_sg_n2"] = note1
else
forms["nom_sg_n"] = stem .. "ud"
forms["acc_sg_n"] = stem .. "ud"
end
forms["voc_sg_m"] = "-"
forms["voc_sg_f"] = "-"
forms["voc_sg_n"] = "-"
forms["voc_pl_m"] = "-"
forms["voc_pl_f"] = "-"
forms["voc_pl_n"] = "-"
empty_table(categories)
elseif arg1 == "illic" or arg1 == "istic" or arg1 == "isthic" then
data.title = glossary_link("demonstrative") .. " " .. singularize(data.pos)
local stem, unattested = arg1:sub(1, -3), data.unattested
forms["nom_sg_m"] = stem .. "ic"
forms["nom_sg_f"] = stem .. "aec"
forms["nom_sg_n"] = {stem .. "uc", stem .. "ucce", stem .. "oc"}
forms["gen_sg_m"] = stem .. "ī̆usce"
forms["gen_sg_f"] = stem .. "ī̆usce"
forms["gen_sg_n"] = stem .. "ī̆usce"
forms["dat_sg_m"] = stem .. "īc"
forms["dat_sg_f"] = stem .. "īc"
forms["dat_sg_n"] = stem .. "īc"
forms["acc_sg_m"] = stem .. "unc"
forms["acc_sg_f"] = stem .. "anc"
forms["acc_sg_n"] = {stem .. "uc", stem .. "ucce", stem .. "oc"}
forms["abl_sg_m"] = stem .. "ōc"
forms["abl_sg_f"] = stem .. "āc"
forms["abl_sg_n"] = stem .. "ōc"
forms["loc_sg_m"] = deep_copy(forms["gen_sg_m"])
forms["loc_sg_f"] = deep_copy(forms["gen_sg_f"])
forms["loc_sg_n"] = deep_copy(forms["gen_sg_n"])
forms["nom_pl_m"] = stem .. "īsce"
forms["nom_pl_f"] = stem .. "aec"
forms["nom_pl_n"] = stem .. "aec"
forms["gen_pl_m"] = stem .. "ōrunc"
unattested["gen_pl_m"] = true
forms["gen_pl_f"] = stem .. "ārunc"
unattested["gen_pl_f"] = true
forms["gen_ok_n"] = stem .. "ōrunc"
unattested["gen_pl_n"] = true
forms["dat_pl_m"] = stem .. "īsce"
forms["dat_pl_f"] = stem .. "īsce"
forms["dat_pl_n"] = stem .. "īsce"
forms["acc_pl_m"] = stem .. "ōsce"
forms["acc_pl_f"] = stem .. "āsce"
forms["acc_pl_n"] = stem .. "aec"
forms["abl_pl_m"] = stem .. "īsce"
forms["abl_pl_f"] = stem .. "īsce"
forms["abl_pl_n"] = stem .. "īsce"
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_f"] = deep_copy(forms["abl_pl_f"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
elseif arg1 == "hice" then
data.title = glossary_link("demonstrative") .. " pronoun"
forms["nom_sg_m"] = "hice"
forms["nom_sg_f"] = "haece"
forms["nom_sg_n"] = "hoce"
forms["nom_pl_m"] = "hīce"
forms["nom_pl_f"] = "haece"
forms["nom_pl_n"] = "haece"
forms["gen_sg_m"] = "huiusce"
forms["gen_sg_f"] = "huiusce"
forms["gen_sg_n"] = "huiusce"
forms["gen_pl_m"] = {"hōrunce", "hōrumce"}
forms["gen_pl_f"] = {"hārunce", "hārumce"}
forms["gen_pl_n"] = {"hōrunce", "hōrumce"}
forms["dat_sg_m"] = "huīce"
forms["dat_sg_f"] = "huīce"
forms["dat_sg_n"] = "huīce"
forms["dat_pl_m"] = "hīsce"
forms["dat_pl_f"] = "hīsce"
forms["dat_pl_n"] = "hīsce"
forms["acc_sg_m"] = "hunce"
forms["acc_sg_f"] = "hance"
forms["acc_sg_n"] = "hoce"
forms["acc_pl_m"] = "hōsce"
forms["acc_pl_f"] = "hāsce"
forms["acc_pl_n"] = "haece"
forms["abl_sg_m"] = "hōce"
forms["abl_sg_f"] = "hāce"
forms["abl_sg_n"] = "hōce"
forms["abl_pl_m"] = "hīsce"
forms["abl_pl_f"] = "hīsce"
forms["abl_pl_n"] = "hīsce"
forms["loc_sg_m"] = deep_copy(forms["gen_sg_m"])
forms["loc_sg_f"] = deep_copy(forms["gen_sg_f"])
forms["loc_sg_n"] = deep_copy(forms["gen_sg_n"])
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_f"] = deep_copy(forms["abl_pl_f"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
elseif arg1 == "plūs" then
data.title = glossary_link("irregular") .. " " .. decl_link("third") .. " comparative " .. singularize(pos) .. ", plural-only in Classical Latin"
local note1 = "None of the singular forms are used as adjectives in Classical Latin."
forms["nom_sg_n"] = "plūs"
notes["nom_sg_n1"] = note1
forms["nom_pl_m"] = "plūrēs"
forms["nom_pl_n"] = "plūra"
forms["gen_sg_m"] = "plūris"
notes["gen_sg_m1"] = note1
forms["gen_sg_n"] = "plūris"
notes["gen_sg_n1"] = note1
forms["gen_pl_m"] = "plūrium"
forms["gen_pl_n"] = "plūrium"
forms["dat_sg_m"] = "plūrī"
notes["dat_sg_m1"] = note1
forms["dat_sg_n"] = "plūrī"
notes["dat_sg_n1"] = note1
forms["dat_pl_m"] = "plūribus"
forms["dat_pl_n"] = "plūribus"
forms["acc_sg_m"] = "plūrem"
notes["acc_sg_m1"] = note1
forms["acc_sg_f"] = "plūrem"
notes["acc_sg_f1"] = note1
forms["acc_sg_n"] = "plūs"
notes["acc_sg_n1"] = note1
forms["acc_pl_m"] = {"plūrēs", "plūrīs"}
forms["acc_pl_n"] = "plūra"
forms["abl_sg_m"] = {"plūrī", "plūre"}
notes["abl_sg_m1"] = note1
notes["abl_sg_m2"] = note1
forms["abl_sg_f"] = {"plūrī", "plūre"}
notes["abl_sg_f1"] = note1
notes["abl_sg_f2"] = note1
forms["abl_sg_n"] = {"plūrī", "plūre"}
notes["abl_sg_n1"] = note1
notes["abl_sg_n2"] = note1
forms["abl_pl_m"] = "plūribus"
forms["abl_pl_n"] = "plūribus"
forms["voc_sg_n"] = "plūs"
notes["voc_sg_n1"] = note1
forms["voc_pl_m"] = "plūrēs"
forms["voc_pl_n"] = "plūra"
forms["loc_sg_m"] = deep_copy(forms["abl_sg_m"])
notes["loc_sg_m1"] = note1
notes["loc_sg_m2"] = note1
forms["loc_sg_f"] = deep_copy(forms["abl_sg_f"])
notes["loc_sg_f1"] = note1
notes["loc_sg_f2"] = note1
forms["loc_sg_n"] = deep_copy(forms["abl_sg_n"])
notes["loc_sg_n1"] = note1
notes["loc_sg_n2"] = note1
forms["loc_pl_m"] = deep_copy(forms["abl_pl_m"])
forms["loc_pl_n"] = deep_copy(forms["abl_pl_n"])
insert_if_not(categories, "Latin third declension " .. pos)
insert_if_not(categories, "Latin third declension " .. pos .. " of one termination")
elseif umatch(arg1, "^egō̆?$") or arg1 == "nōs" then
data.title = glossary_link("personal") .. " pronoun"
forms["nom_sg_m"] = arg1
forms["nom_pl_m"] = "nōs"
forms["gen_sg_m"] = "meī"
forms["gen_pl_m"] = {"nostrī", "nostrum"}
forms["dat_sg_m"] = "mihī̆"
forms["dat_pl_m"] = "nōbīs"
forms["acc_sg_m"] = {"mē", "mēmē"}
forms["acc_pl_m"] = "nōs"
forms["abl_sg_m"] = {"mē", "mēmē"}
forms["abl_pl_m"] = "nōbīs"
forms["voc_sg_m"] = arg1
forms["voc_pl_m"] = "nōs"
elseif arg1 == "tū" or arg1 == "vōs" then
data.title = glossary_link("personal") .. " pronoun"
forms["nom_sg_m"] = arg1
forms["nom_pl_m"] = "vōs"
forms["gen_sg_m"] = "tuī"
forms["gen_pl_m"] = {"vestrī", "vestrum"}
forms["dat_sg_m"] = "tibī̆"
forms["dat_pl_m"] = "vōbīs"
forms["acc_sg_m"] = {"tē", "tētē"}
forms["acc_pl_m"] = "vōs"
forms["abl_sg_m"] = {"tē", "tētē"}
forms["abl_pl_m"] = "vōbīs"
forms["voc_sg_m"] = arg1
forms["voc_pl_m"] = "vōs"
elseif arg1 == "suī" then
data.title = glossary_link("reflexive") .. " pronoun"
forms["nom_sg_m"] = "-"
forms["nom_pl_m"] = "-"
forms["gen_sg_m"] = arg1
forms["gen_pl_m"] = forms["gen_sg_m"]
forms["dat_sg_m"] = "sibī̆"
forms["dat_pl_m"] = forms["dat_sg_m"]
forms["acc_sg_m"] = {"sē", "sēsē"}
forms["acc_pl_m"] = {"sē", "sēsē"}
forms["abl_sg_m"] = {"sē", "sēsē"}
forms["abl_pl_m"] = {"sē", "sēsē"}
forms["voc_sg_m"] = "-"
forms["voc_pl_m"] = "-"
elseif arg1 == "is" or arg1 == "īdem" then
data.title = glossary_link("demonstrative") .. " pronoun"
local note1 = "The dat. singular is found spelled <small>EIEI</small> (here represented as ''ēī'') and scanned as two longs in Plautus, but also as a monosyllable. The latter is its normal scansion in Classical. Other spellings include <small>EEI, IEI</small>."
local note2 = "The nom./dat./abl. plural forms regularly developed into a monosyllable /iː(s)/, with later remodelling - compare the etymology of [[deus]]. This /iː/ was normally spelled as <small>EI</small> during and as <small>II</small> after the Republic; a disyllabic ''iī'', spelled <small>II, Iꟾ</small>, appears in Silver Age poetry, while disyllabic ''eīs'' is only post-Classical. Other spellings include <small>EEI(S), EIEI(S), IEI(S)</small>."
forms["nom_sg_m"] = "is"
forms["nom_sg_f"] = "ea"
forms["nom_sg_n"] = "id"
forms["nom_pl_m"] = {"iī", "eī", "ī"}
notes["nom_pl_m1"] = note2
forms["nom_pl_f"] = "eae"
forms["nom_pl_n"] = "ea"
forms["gen_sg_m"] = {"eius", "ejus"}
forms["gen_sg_f"] = {"eius", "ejus"}
forms["gen_sg_n"] = {"eius", "ejus"}
forms["gen_pl_m"] = {"eōrum", "eum"}
forms["gen_pl_f"] = "eārum"
forms["gen_pl_n"] = {"eōrum", "eum"}
forms["dat_sg_m"] = {"eī", "e͡i", "ēī"}
notes["dat_sg_m1"] = note1
forms["dat_sg_f"] = {"eī", "e͡i", "ēī", "eae"}
notes["dat_sg_f1"] = note1
forms["dat_sg_n"] = {"eī", "e͡i", "ēī"}
notes["dat_sg_n1"] = note1
forms["dat_pl_m"] = {"iīs", "eīs", "īs", "ībus"}
notes["dat_pl_m1"] = note2
forms["dat_pl_f"] = {"iīs", "eīs", "īs", "eābus"}
notes["dat_pl_f1"] = note2
forms["dat_pl_n"] = {"iīs", "eīs", "īs"}
notes["dat_pl_n1"] = note2
forms["acc_sg_m"] = "eum"
forms["acc_sg_f"] = "eam"
forms["acc_sg_n"] = "id"
forms["acc_pl_m"] = "eōs"
forms["acc_pl_f"] = "eās"
forms["acc_pl_n"] = "ea"
forms["abl_sg_m"] = "eō"
forms["abl_sg_f"] = "eā"
forms["abl_sg_n"] = "eō"
forms["abl_pl_m"] = {"iīs", "eīs", "īs"}
notes["abl_pl_m1"] = note2
forms["abl_pl_f"] = {"iīs", "eīs", "īs"}
notes["abl_pl_f1"] = note2
forms["abl_pl_n"] = {"iīs", "eīs", "īs"}
notes["abl_pl_n1"] = note2
if arg1 == "īdem" then
forms["nom_sg_m"] = "ī"
forms["nom_sg_n"] = "i"
forms["acc_sg_n"] = "i"
end
elseif arg1 == "quis" or arg1 == "quī" then
local note1 = "''Qua'' (with short ''ă'') occurs only as an indefinite pronoun or determiner placed immediately after ''[[si#Latin|sī]]'', ''[[ne#Latin|nē]]'', or ''[[num#Latin|num]]''. The combinations ''[[siqua#Latin|sīqua]]'', ''[[nequa#Latin|nēqua]]'', and ''[[numqua#Latin|numqua]]'' are sometimes written without spacing (as also are the masculines ''[[siquis#Latin|sīquis]]'', ''[[nequis#Latin|nēquis]]'' and ''[[numquis#Latin|numquis]]''). Compare ''[[aliquis#Latin|aliquis, aliqua, aliquid]]''. ''Quae'' can also be used instead of ''quă''. ''Quă'' is never used as an interrogative pronoun/determiner, relative pronoun/determiner, or feminine nominative plural."
local note2 = "In Republican Latin or earlier, alternative spellings could be found for the following forms of ''[[qui#Latin|quī]]''/''[[quis#Latin|quis]]'' and its compounds: the masculine nominative singular or plural ''quī'' (old spelling ''[[quei]]''), the genitive singular ''cuius'' (old spelling ''[[quoius]]''), the dative singular ''cui'' (old spelling ''[[quoi]]'' or ''[[quoiei]]''), the dative/ablative plural ''quīs'' (old spelling ''[[queis]]'')."
local note3 = "Feminine ''quis'' and ''quem'' are attested mainly in early Latin authors (Ennius, Pacuvius, and Plautus)."
local id = "id"
if arg1 == "quī" then
id = "od"
forms["nom_sg_m"] = {"quī", "quis"}
notes["nom_sg_m1"] = note2
forms["nom_sg_f"] = {"quae", "qua"}
notes["nom_sg_f2"] = note1
forms["acc_sg_f"] = "quam"
forms["abl_sg_m"] = "quō"
forms["abl_sg_f"] = "quā"
forms["abl_sg_n"] = "quō"
data.title = glossary_link("relative") .. "/" .. glossary_link("interrogative") .. " determiner"
else
forms["nom_sg_m"] = {"quis", "quī"}
notes["nom_sg_m2"] = note2
forms["nom_sg_f"] = {"quae", "qua", "quis"}
notes["nom_sg_f2"] = note1
notes["nom_sg_f3"] = note3
forms["acc_sg_f"] = {"quam", "quem"}
notes["acc_sg_f2"] = note3
forms["abl_sg_m"] = {"quō", "quī"}
forms["abl_sg_f"] = {"quā", "quī"}
forms["abl_sg_n"] = {"quō", "quī"}
data.title = glossary_link("relative") .. "/" .. glossary_link("interrogative") .. " pronoun"
end
forms["nom_sg_n"] = "qu"..id
forms["nom_pl_m"] = "quī"
notes["nom_pl_m1"] = note2
forms["nom_pl_f"] = "quae"
forms["nom_pl_n"] = {"quae", "qua"}
notes["nom_pl_n2"] = note1
forms["gen_sg_m"] = "cuius"
forms["gen_sg_f"] = "cuius"
forms["gen_sg_n"] = "cuius"
notes["gen_sg_m1"] = note2
notes["gen_sg_f1"] = note2
notes["gen_sg_n1"] = note2
forms["gen_pl_m"] = "quōrum"
forms["gen_pl_f"] = "quārum"
forms["gen_pl_n"] = "quōrum"
forms["dat_sg_m"] = "cui"
forms["dat_sg_f"] = "cui"
forms["dat_sg_n"] = "cui"
notes["dat_sg_m1"] = note2
notes["dat_sg_f1"] = note2
notes["dat_sg_n1"] = note2
forms["dat_pl_m"] = {"quibus", "quīs"}
forms["dat_pl_f"] = {"quibus", "quīs"}
forms["dat_pl_n"] = {"quibus", "quīs"}
notes["dat_pl_m2"] = note2
notes["dat_pl_f2"] = note2
notes["dat_pl_n2"] = note2
forms["acc_sg_m"] = "quem"
forms["acc_sg_n"] = "qu"..id
forms["acc_pl_m"] = "quōs"
forms["acc_pl_f"] = "quās"
forms["acc_pl_n"] = {"quae", "qua"}
notes["acc_pl_n2"] = note1
forms["abl_pl_m"] = {"quibus", "quīs"}
forms["abl_pl_f"] = {"quibus", "quīs"}
forms["abl_pl_n"] = {"quibus", "quīs"}
notes["abl_pl_m2"] = note2
notes["abl_pl_f2"] = note2
notes["abl_pl_n2"] = note2
elseif arg1 == "aliquī" then
data.title = glossary_link("indefinite") .. " " .. glossary_link("determiner")
local note1 = "Normatively, [[aliqui#Latin|aliquī]] is a determiner (used adjectivally) and [[aliquis#Latin|aliquis]] is a pronoun (used substantively), but the opposite usages can be found, even among the best Classical writers."
local note2 = "The feminine nominative singular form is usually ''aliqua'', but there are a handful of possible examples of ''aliquae'' as a feminine nominative singular form; see [[Citations:aliquae]]. The feminine nominative plural can only be ''aliquae'', and there are perhaps no solid examples of the neuter nominative/accusative plural taking any form other than ''aliqua''."
local note3 = "Alternative spelling [[aliquoius]] (used in Republican Latin or earlier)."
local note4 = "Alternative spelling [[aliqueis]] (used in Republican Latin or earlier)."
local note5 = "Alternative spelling [[aliquoi]] (used in Republican Latin or earlier)."
forms["nom_sg_m"] = {"aliquī", "aliquis"}
notes["nom_sg_m2"] = note1
forms["nom_sg_f"] = "aliqua"
notes["nom_sg_f1"] = note2
forms["nom_sg_n"] = "aliquod"
forms["nom_pl_m"] = "aliquī"
forms["nom_pl_f"] = "aliquae"
notes["nom_pl_f1"] = note2
forms["nom_pl_n"] = "aliqua"
notes["nom_pl_n1"] = note2
forms["gen_sg_m"] = "alicuius"
notes["gen_sg_m1"] = note3
forms["gen_sg_f"] = "alicuius"
notes["gen_sg_f1"] = note3
forms["gen_sg_n"] = "alicuius"
notes["gen_sg_n1"] = note3
forms["gen_pl_m"] = "aliquōrum"
forms["gen_pl_f"] = "aliquārum"
forms["gen_pl_n"] = "aliquōrum"
forms["dat_sg_m"] = "alicui"
notes["dat_sg_m1"] = note5
forms["dat_sg_f"] = "alicui"
notes["dat_sg_f1"] = note5
forms["dat_sg_n"] = "alicui"
notes["dat_sg_n1"] = note5
forms["dat_pl_m"] = {"aliquīs", "aliquibus"}
notes["dat_pl_m1"] = note4
forms["dat_pl_f"] = {"aliquīs", "aliquibus"}
notes["dat_pl_f1"] = note4
forms["dat_pl_n"] = {"aliquīs", "aliquibus"}
notes["dat_pl_n1"] = note4
forms["acc_sg_m"] = "aliquem"
forms["acc_sg_f"] = "aliquam"
forms["acc_sg_n"] = "aliquod"
forms["acc_pl_m"] = "aliquōs"
forms["acc_pl_f"] = "aliquās"
forms["acc_pl_n"] = "aliqua"
notes["acc_pl_n1"] = note2
forms["abl_sg_m"] = "aliquō"
forms["abl_sg_f"] = "aliquā"
forms["abl_sg_n"] = "aliquō"
forms["abl_pl_m"] = {"aliquīs", "aliquibus"}
notes["abl_pl_m1"] = note4
forms["abl_pl_f"] = {"aliquīs", "aliquibus"}
notes["abl_pl_f1"] = note4
forms["abl_pl_n"] = {"aliquīs", "aliquibus"}
notes["abl_pl_n1"] = note4
elseif arg1 == "quisquam" then
local note1 = "Only attested in postclassical Latin. In Classical Latin, forms of [[ullus#Latin|ūllus]] were used instead."
local note2 = "Only attested as a feminine form in the preclassical Latin of authors like Plautus."
local note3 = "Attested only once in Classical Latin. Usually [[ullus#Latin|ūllam]] was used instead."
local note4 = "Attested, but rare in Classical Latin. Usually [[ullus#Latin|ūllō]] was used instead."
data.title = glossary_link("negative polarity item", "negative polarity") .. " " .. glossary_link("indefinite") .. " " .. glossary_link("determiner")
forms["nom_sg_m"] = "quisquam"
forms["nom_sg_f"] = {"quaequam", "quisquam"}
notes["nom_sg_f1"] = note1
notes["nom_sg_f2"] = note2
forms["nom_sg_n"] = "quodquam"
notes["nom_sg_n1"] = note1
forms["nom_pl_m"] = "quīquam"
notes["nom_pl_m1"] = note1
forms["nom_pl_f"] = "quaequam"
notes["nom_pl_f1"] = note1
forms["nom_pl_n"] = "quaequam"
notes["nom_pl_n1"] = note1
forms["gen_sg_m"] = "cuiusquam"
forms["gen_sg_f"] = "cuiusquam"
forms["gen_sg_n"] = "cuiusquam"
forms["gen_pl_m"] = "quōrumquam"
notes["gen_pl_m1"] = note1
forms["gen_pl_f"] = "quārumquam"
notes["gen_pl_f1"] = note1
forms["gen_pl_n"] = "quōrumquam"
notes["gen_pl_n1"] = note1
forms["dat_sg_m"] = "cuiquam"
forms["dat_sg_f"] = "cuiquam"
forms["dat_sg_n"] = "cuiquam"
forms["dat_pl_m"] = "quibusquam"
notes["dat_pl_m1"] = note1
forms["dat_pl_f"] = "quibusquam"
notes["dat_pl_f1"] = note1
forms["dat_pl_n"] = "quibusquam"
notes["dat_pl_n1"] = note1
forms["acc_sg_m"] = "quemquam"
forms["acc_sg_f"] = {"quamquam", "quemquam"}
notes["acc_sg_f1"] = note3
notes["acc_sg_f2"] = note2
forms["acc_sg_n"] = "quodquam"
notes["acc_sg_n1"] = note1
forms["acc_pl_m"] = "quōsquam"
notes["acc_pl_m1"] = note1
forms["acc_pl_f"] = "quāsquam"
notes["acc_pl_f1"] = note1
forms["acc_pl_n"] = "quaequam"
notes["acc_pl_n1"] = note1
forms["abl_sg_m"] = {"quōquam", "quīquam"}
notes["abl_sg_m1"] = note4
notes["abl_sg_m2"] = note2
forms["abl_sg_f"] = "quāquam"
notes["abl_sg_f1"] = note1
forms["abl_sg_n"] = "quōquam"
notes["abl_sg_n1"] = note4
forms["abl_pl_m"] = "quibusquam"
notes["abl_pl_m1"] = note1
forms["abl_pl_f"] = "quibusquam"
notes["abl_pl_f1"] = note1
forms["abl_pl_n"] = "quibusquam"
notes["abl_pl_n1"] = note1
forms["voc_sg_m"] = "quisquam"
notes["voc_sg_m1"] = note1
forms["voc_sg_f"] = "quaequam"
notes["voc_sg_f1"] = note1
forms["voc_sg_n"] = "quodquam"
notes["voc_sg_n1"] = note1
forms["voc_pl_m"] = "quīquam"
notes["voc_pl_m1"] = note1
forms["voc_pl_f"] = "quaequam"
notes["voc_pl_f1"] = note1
forms["voc_pl_n"] = "quaequam"
notes["voc_pl_n1"] = note1
elseif arg1 == "quisquis" then
data.title = glossary_link("relative") .. "/" .. glossary_link("interrogative") .. " pronoun"
forms["nom_sg_m"] = "quisquis"
forms["nom_sg_f"] = "quisquis"
forms["nom_sg_n"] = {"quidquid", "quicquid"}
forms["nom_pl_m"] = "quīquī"
forms["nom_pl_f"] = "quaequae"
forms["nom_pl_n"] = "quaequae"
forms["gen_sg_m"] = "cuiuscuius"
forms["gen_sg_f"] = "cuiuscuius"
forms["gen_sg_n"] = "cuiuscuius"
forms["gen_pl_m"] = "quōrumquōrum"
forms["gen_pl_f"] = "quārumquārum"
forms["gen_pl_n"] = "quōrumquōrum"
forms["dat_sg_m"] = "cuicui"
forms["dat_sg_f"] = "cuicui"
forms["dat_sg_n"] = "cuicui"
forms["dat_pl_m"] = {"quibusquibus", "quīsquīs"}
forms["dat_pl_f"] = {"quibusquibus", "quīsquīs"}
forms["dat_pl_n"] = {"quibusquibus", "quīsquīs"}
forms["acc_sg_m"] = "quemquem"
forms["acc_sg_f"] = "quamquam"
forms["acc_sg_n"] = {"quidquid", "quicquid"}
forms["acc_pl_m"] = "quōsquōs"
forms["acc_pl_f"] = "quāsquās"
forms["acc_pl_n"] = "quaequae"
forms["abl_sg_m"] = "quōquō"
forms["abl_sg_f"] = "quāquā"
forms["abl_sg_n"] = "quōquō"
forms["abl_pl_m"] = {"quibusquibus", "quīsquīs"}
forms["abl_pl_f"] = {"quibusquibus", "quīsquīs"}
forms["abl_pl_n"] = {"quibusquibus", "quīsquīs"}
forms["voc_sg_m"] = "quisquis"
forms["voc_sg_f"] = "quisquis"
forms["voc_sg_n"] = {"quidquid", "quicquid"}
forms["voc_pl_m"] = "quīquī"
forms["voc_pl_f"] = "quaequae"
forms["voc_pl_n"] = "quaequae"
elseif arg1 == "ecquis" then
local note1 = "Unattested in classical Latin."
local note2 = "Attested only twice in Classical Latin."
data.title = glossary_link("interrogative") .. " pronoun"
forms["nom_sg_m"] = {"ecquis", "ecquī"}
forms["nom_sg_f"] = {"ecqua", "ecquae"}
forms["nom_sg_n"] = "ecquid"
forms["nom_pl_m"] = "ecquī"
forms["nom_pl_f"] = "ecquae"
forms["nom_pl_n"] = {"ecqua", "ecquae"}
forms["gen_sg_m"] = "eccuius"
forms["gen_sg_f"] = "eccuius"
forms["gen_sg_n"] = "eccuius"
notes["gen_sg_m1"] = note1
notes["gen_sg_f1"] = note1
notes["gen_sg_n1"] = note1
forms["dat_sg_m"] = "eccui"
forms["dat_sg_f"] = "eccui"
forms["dat_sg_n"] = "eccui"
notes["dat_sg_m1"] = note2
notes["dat_sg_f1"] = note2
notes["dat_sg_n1"] = note2
forms["acc_sg_m"] = "ecquem"
forms["acc_sg_f"] = "ecquam"
forms["acc_sg_n"] = "ecquod"
forms["acc_pl_m"] = "ecquōs"
forms["acc_pl_f"] = "ecquās"
forms["acc_pl_n"] = {"ecqua", "ecquae"}
forms["abl_sg_m"] = {"ecquō", "ecquī"}
forms["abl_sg_f"] = {"ecquā", "ecquī"}
forms["abl_sg_n"] = {"ecquō", "ecquī"}
elseif arg1 == "quīdam" then
local note1 = "The genitive singular was spelled [[quoiusdam#Latin|''quoiusdam'']] before the Augustan period."
local note2 = "The dative singular was spelled [[quoidam#Latin|''quoidam'']] before the Augustan period."
local note3 = "An alternative masculine nominative/accusative plural form [[quesdam#Latin|''quēsdam'']] occurs in Accius."
local note4 = "The dative/ablative plural has a rare alternative form [[quisdam#Latin|''quīsdam'']]/[[queisdam#Latin|''queisdam'']]."
data.title = glossary_link("indefinite") .. " pronoun"
forms["nom_sg_m"] = "quīdam"
forms["nom_sg_f"] = "quaedam"
forms["nom_sg_n"] = "quiddam"
forms["nom_pl_m"] = "quīdam"
notes["nom_pl_m1"] = note3
forms["nom_pl_f"] = "quaedam"
forms["nom_pl_n"] = "quaedam"
forms["gen_sg_m"] = "cuiusdam"
forms["gen_sg_f"] = "cuiusdam"
forms["gen_sg_n"] = "cuiusdam"
notes["gen_sg_m1"] = note1
notes["gen_sg_f1"] = note1
notes["gen_sg_n1"] = note1
forms["gen_pl_m"] = {"quōrundam", "quōrumdam"}
forms["gen_pl_f"] = {"quārundam", "quārumdam"}
forms["gen_pl_n"] = {"quōrundam", "quōrumdam"}
forms["dat_sg_m"] = "cuidam"
forms["dat_sg_f"] = "cuidam"
forms["dat_sg_n"] = "cuidam"
notes["dat_sg_m1"] = note2
notes["dat_sg_f1"] = note2
notes["dat_sg_n1"] = note2
forms["dat_pl_m"] = "quibusdam"
forms["dat_pl_f"] = "quibusdam"
forms["dat_pl_n"] = "quibusdam"
notes["dat_pl_m1"] = note4
notes["dat_pl_f1"] = note4
notes["dat_pl_n1"] = note4
forms["acc_sg_m"] = {"quendam", "quemdam"}
forms["acc_sg_f"] = {"quandam", "quamdam"}
forms["acc_sg_n"] = "quiddam"
forms["acc_pl_m"] = "quōsdam"
notes["acc_pl_m1"] = note3
forms["acc_pl_f"] = "quāsdam"
forms["acc_pl_n"] = "quaedam"
forms["abl_sg_m"] = "quōdam"
forms["abl_sg_f"] = "quādam"
forms["abl_sg_n"] = "quōdam"
forms["abl_pl_m"] = "quibusdam"
forms["abl_pl_f"] = "quibusdam"
forms["abl_pl_n"] = "quibusdam"
notes["abl_pl_m1"] = note4
notes["abl_pl_f1"] = note4
notes["abl_pl_n1"] = note4
elseif arg1 == "nēmō" then
local note1 = "The genitive [[neminis|''nēminis'']] is not used in Classical Latin, and is generally also avoided by later authors."
local note2 = "The ablative [[nemine|''nēmine'']] is not used in Classical Latin, but can be seen in authors from the Imperial period onwards."
data.title = "Negative pronoun and " .. glossary_link("determiner")
forms["nom_sg_m"] = "nēmō"
forms["nom_sg_f"] = "nēmō"
forms["gen_sg_m"] = {"nūllī̆us", "nēminis"}
forms["gen_sg_f"] = {"nūllī̆us", "nēminis"}
notes["gen_sg_m2"] = note1
notes["gen_sg_f2"] = note1
forms["dat_sg_m"] = "nēminī"
forms["dat_sg_f"] = "nēminī"
forms["acc_sg_m"] = "nēminem"
forms["acc_sg_f"] = "nēminem"
forms["abl_sg_m"] = {"nūllō", "nēmine"}
forms["abl_sg_f"] = {"nūllā", "nēmine"}
notes["abl_sg_m2"] = note2
notes["abl_sg_f2"] = note2
else
error('adjective ' .. arg1 .. ' not recognized')
end
end
return decl
-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet:
shz7o2mxrluungq1okp2hafndcg81uc
Modul:la-verb/data
828
75450
344380
221577
2026-05-25T23:10:02Z
Hakimi97
2668
344380
Scribunto
text/plain
local data = {}
data.allowed_subtypes = require("Module:table").listToSet{
"3only",
"i",
"alwayssyncperf",
"depon",
"f",
"fp",
"highlydef", -- can be specified manually in the headword to display "highly defective"
"impers",
"imponly",
"m",
"mp",
"n",
"nofutr",
"nofutractvptc",
"noger",
"noimp",
"noinf",
"nopass",
"noperf",
"nopres",
"nosup",
"nound",
"np",
"old2sgimp",
"oldimpffutr",
"optsemidepon",
"optsyncperf",
"p3inf",
"pass3only",
"passimpers",
"perfaspres",
"poetsyncperf",
"semidepon",
"sigm",
"sigmpasv",
"suffix",
"supfutractvonly",
}
return data
0mpgxjz3jszv9oe1206y9wa4fg9geex
Wikikamus:en/sing
4
84456
344289
237250
2026-05-25T13:51:25Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/Sing]] ke [[Wikikamus:en/sing]] tanpa meninggalkan lencongan: Tajuk salah eja
237250
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata kerja===
{{inti|en|kata kerja}}
# menyanyi <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|I sing.<!--Ganti dengan contoh ayat dalam bahasa Inggeris-->|saya menyanyi.<!--Ganti dengan terjemahan contoh ayat dalam bahasa Melayu-->}}
li7jjkvh7b4sw0v3dhwju63ddbljw89
344290
344289
2026-05-25T13:51:44Z
PeaceSeekers
3334
344290
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata kerja===
{{inti|en|kata kerja}}
# [[nyanyi]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|I sing.<!--Ganti dengan contoh ayat dalam bahasa Inggeris-->|saya menyanyi.<!--Ganti dengan terjemahan contoh ayat dalam bahasa Melayu-->}}
o09u4via7e4ahyolh6dxi8v4rmte1k8
Wikikamus:en/observe
4
84462
344284
237251
2026-05-25T13:49:32Z
PeaceSeekers
3334
344284
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata kerja===
{{inti|en|kata kerja}}
# [[perhati]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|I observe the students in the classroom.<!--Ganti dengan contoh ayat dalam bahasa Inggeris-->|Saya perhati para pelajar di dalam kelas.<!--Ganti dengan terjemahan contoh ayat dalam bahasa Melayu-->}}
t5oqkq3wjbwstjpxhifnf29zyvgyflf
344285
344284
2026-05-25T13:49:49Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/Observe]] ke [[Wikikamus:en/observe]] tanpa meninggalkan lencongan: Tajuk salah eja
344284
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata kerja===
{{inti|en|kata kerja}}
# [[perhati]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|I observe the students in the classroom.<!--Ganti dengan contoh ayat dalam bahasa Inggeris-->|Saya perhati para pelajar di dalam kelas.<!--Ganti dengan terjemahan contoh ayat dalam bahasa Melayu-->}}
t5oqkq3wjbwstjpxhifnf29zyvgyflf
Wikikamus:en/flexible
4
84467
344283
237257
2026-05-25T13:48:41Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/Flexible]] ke [[Wikikamus:en/flexible]] tanpa meninggalkan lencongan: Tajuk salah eja
237257
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata sifat ===
# Lentur <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|a Taekwondo athlete have a flexible body<!--Ganti dengan contoh ayat dalam bahasa Inggeris-->|seorang atlet Taekwondo mempunyai badan yang lentur<!--Ganti dengan terjemahan contoh ayat dalam bahasa Melayu-->}}
05azu411mtw79xp2q3u7scyukfho9mk
Wikikamus:ja/車
4
89768
344280
250657
2026-05-25T13:04:58Z
Ssante10
10156
344280
wikitext
text/x-wiki
==Bahasa Jepun==
===Kata nama===
{{inti|ja|kata nama}}
# kereta
skdeutoi0ltf5m8f0mjow5vlrm70cht
Wikikamus:ja/置く
4
89875
344271
250766
2026-05-25T12:58:11Z
Ssante10
10156
344271
wikitext
text/x-wiki
==Bahasa Jepun==
===Kata kerja===
{{inti|ja|kata kerja}}
# Meletakkan
am6xr6o71t2ay6j2dgdqgicsdekw11k
Wikikamus:ja/犬
4
90000
344274
250895
2026-05-25T13:00:47Z
Ssante10
10156
344274
wikitext
text/x-wiki
==Bahasa Jepun==
===Kata nama===
{{inti|ja|kata nama}}
# Anjing
pummok2cq58u94x29kjgm1bin30biym
Wikikamus:en/traffic
4
92598
344291
254347
2026-05-25T13:53:01Z
PeaceSeekers
3334
344291
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata nama===
{{inti|en|kata nama}}
# [[trafik]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|Kuala Lumpur always had a busy '''traffic''' almost everyday|Kuala Lumpur sentiasa mempunyai '''trafik''' yang sibuk hampir setiap hari}}
m6ci85ofdo5mnjgwhja2ybt9mgb2pu5
344292
344291
2026-05-25T13:53:26Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/Traffic]] ke [[Wikikamus:en/traffic]] tanpa meninggalkan lencongan: Tajuk salah eja
344291
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata nama===
{{inti|en|kata nama}}
# [[trafik]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|Kuala Lumpur always had a busy '''traffic''' almost everyday|Kuala Lumpur sentiasa mempunyai '''trafik''' yang sibuk hampir setiap hari}}
m6ci85ofdo5mnjgwhja2ybt9mgb2pu5
Wikikamus:en/river
4
92600
344286
254349
2026-05-25T13:50:21Z
PeaceSeekers
3334
344286
wikitext
text/x-wiki
]==Bahasa Inggeris==
===Kata nama===
{{inti|en|kata nama}}
# [[sungai]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|That '''river''' current is very strong.|Arus '''sungai''' itu sangat kuat.}}
htx5c9jdde96n6cawvvp7dpwydmmvpk
344287
344286
2026-05-25T13:50:34Z
PeaceSeekers
3334
344287
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata nama===
{{inti|en|kata nama}}
# [[sungai]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|That '''river''' current is very strong.|Arus '''sungai''' itu sangat kuat.}}
9z40uwdhz6qyemykmqyj15xraa092n3
344288
344287
2026-05-25T13:50:51Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/River]] ke [[Wikikamus:en/river]] tanpa meninggalkan lencongan: Tajuk salah eja
344287
wikitext
text/x-wiki
==Bahasa Inggeris==
===Kata nama===
{{inti|en|kata nama}}
# [[sungai]] <!--Ganti dengan erti kata yang dimasukkan dalam bahasa Melayu-->
#: {{cp|en|That '''river''' current is very strong.|Arus '''sungai''' itu sangat kuat.}}
9z40uwdhz6qyemykmqyj15xraa092n3
Wikikamus:en/undulate
4
103865
344293
268524
2026-05-25T13:54:07Z
PeaceSeekers
3334
PeaceSeekers telah memindahkan laman [[Wikikamus:en/Undulate]] ke [[Wikikamus:en/undulate]] tanpa meninggalkan lencongan: Tajuk salah eja
268524
wikitext
text/x-wiki
{{lemma
|kodbahasa=en
|etimologi=Daripada bahasa Latin ''undulatus'', bentuk lampau bagi ''undulare'' yang bermaksud “berombak”, daripada ''unda'' (“gelombang”).
|sebutan={{IPA|en|/ˈʌn.djʊ.leɪt/}}
|golongankata=kata kerja
|maksud=bergerak atau berbentuk beralun seperti gelombang; naik turun secara lembut dan berterusan.
|contohayat=The flag '''undulated''' gently in the breeze.
|terjemahanayat=Bendera itu '''beralun''' lembut ditiup angin.
}}
8gxj49kb8pj7mkt6aatxwf79489akk4
Wikikamus:dtp/bawang
4
116358
344449
283755
2026-05-26T10:25:12Z
~2026-31405-48
10802
/* Kata nama */
344449
wikitext
text/x-wiki
==Bahasa {{bahasa|dtp}}==
===Kata nama===
{{inti|dtp|kata nama}}
# {{label|1=dtp|2=dialek|3=Liwan}} sungai
5r2lsmcg0lj2u34t2vdrzrcvazcze21
Wikikamus:tmw/ninik
4
116584
344304
342641
2026-05-25T14:08:48Z
Ultron90
4762
344304
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata nama===
{{inti|tmw|kata nama}}
# {{label|tmw|dialek|Bukit Lagong}} [[datuk]] {{cp|tmw|'''Ninik''' ituk sudah tuak.|'''Datuk''' itu sudah tua.}}
5knqev1jg2oa73rz966xwygrpctymhh
Wikikamus:tmw/akuk
4
116607
344305
342360
2026-05-25T14:10:31Z
Ultron90
4762
344305
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata ganti nama===
{{inti|tmw|kata ganti nama}}
# {{label|tmw|dialek|Bukit Lagong}} [[saya]], [[aku]]{{cp|tmw|Namak '''akuk''' Ali.|Nama '''saya''' Ali.}}
2ybb135yrr4zjyh356oc6ptapwr55ob
Wikikamus:tmw/niak
4
116614
344300
342358
2026-05-25T14:04:59Z
Ultron90
4762
344300
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata sendi nama===
{{inti|tmw|kata sendi nama}}
# {{label|tmw|dialek|Bukit Lagong}} [[tiada]] {{cp|tmw|}}
3aco915ny4y0i43htgzgiyebbl7ybnh
Wikikamus:tmw/genui
4
116636
344308
342399
2026-05-25T14:13:09Z
Ultron90
4762
344308
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata nama===
{{inti|tmw|kata nama}}
# {{label|tmw|dialek|Bukit Lagong}} [[nenek]]{{cp|tmw|'''Genui''' ituk dah tuak.|'''Nenek''' itu sudah tua.}}
3nhoh1cijkercs7fjmv05ppxs6yscsl
Wikikamus:tmw/mamak
4
116639
344296
342397
2026-05-25T13:57:49Z
Ultron90
4762
344296
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata nama===
{{inti|tmw|kata nama}}
# {{label|tmw|dialek|Bukit Lagong}} pakcik {{cp|tmw|}}
22d7ugzdp3a0gl639sy5nzth49jh5j7
Wikikamus:tmw/menganyam
4
116746
344312
333039
2026-05-25T14:17:18Z
Ultron90
4762
344312
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata kerja===
{{inti|tmw|kata kerja}}
# {{label|tmw|dialek|Bukit Lagong}} [[menganyam]]{{cp|tmw|Moh kitak '''menganyam'''.|Mari kita '''menganyam'''.}}
gutzopu8vyj9ctym9w9wt287pkze5xy
344313
344312
2026-05-25T14:17:37Z
Ultron90
4762
Ultron90 telah memindahkan laman [[Wikikamus:tmw/Moh kita mengayam]] ke [[Wikikamus:tmw/menganyam]] tanpa meninggalkan lencongan: Tajuk salah eja
344312
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata kerja===
{{inti|tmw|kata kerja}}
# {{label|tmw|dialek|Bukit Lagong}} [[menganyam]]{{cp|tmw|Moh kitak '''menganyam'''.|Mari kita '''menganyam'''.}}
gutzopu8vyj9ctym9w9wt287pkze5xy
Wikikamus:tmw/aka ulan
4
116790
344378
342710
2026-05-25T17:31:15Z
Ultron90
4762
/* Kata nama */
344378
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata nama===
{{inti|tmw|kata nama}}
# {{label|tmw|dialek|Bukit Lagong}} akar untuk merawat luka{{cp|tmw|Ninik caik '''aka ulan''' di hutan.|Datuk pergi mencari '''akar ulan''' di hutan.}}
66veb75iht30r5579iwjvywuhofug38
Wikikamus:tmw/lawa
4
118291
344294
342422
2026-05-25T13:56:06Z
Ultron90
4762
344294
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata sifat===
{{inti|tmw|kata sifat}}
# {{label|tmw|dialek|Bukit Lagong}} [[lawa]], [[cantik]], [[comel]]{{cp|tmw|}}
in5b4z8sbzi78dd0mi2swnu1vleeej8
Wikikamus:tmw/lemuk
4
118501
344295
342551
2026-05-25T13:56:52Z
Ultron90
4762
344295
wikitext
text/x-wiki
==Bahasa {{bahasa|tmw}}==
===Kata nama===
{{inti|tmw|kata nama}}
# {{label|1=tmw|2=dialek|3=Bukit Lagong}} [[lembu]]{{cp|tmw|}}
6isr5bpntoucrwdh3xbxujzs6gka1b0
Wikikamus:ja/起きろ
4
119783
344267
2026-05-25T12:55:32Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # Bangun tidur'
344267
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata kerja===
{{inti|ja|kata kerja}}
# Bangun tidur
rtry4cjo3my611cxnusq5cw7z8h6ym1
Wikikamus:ja/休む
4
119784
344268
2026-05-25T12:56:10Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # Istirahat'
344268
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata kerja===
{{inti|ja|kata kerja}}
# Istirahat
5x7tl855wobgfgusfs9cxqvq10jjxca
Wikikamus:ja/結婚する
4
119785
344269
2026-05-25T12:56:55Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # Menikah'
344269
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata kerja===
{{inti|ja|kata kerja}}
# Menikah
0sjhvft6d26uzavx31p3d3kjn8zmv8d
Wikikamus:ja/話し中
4
119786
344270
2026-05-25T12:57:24Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # Berbicara'
344270
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata kerja===
{{inti|ja|kata kerja}}
# Berbicara
j2ll0jwdeho9n7kvwszpmqjrhiwf2cu
Wikikamus:ja/ライトを消してください
4
119787
344272
2026-05-25T12:58:47Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # Mematikan Lampu'
344272
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata kerja===
{{inti|ja|kata kerja}}
# Mematikan Lampu
spyvjzkha8p69a50rqsqj7p42697txg
Wikikamus:ja/消防署
4
119788
344273
2026-05-25T12:59:46Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Balai Bomba'
344273
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Balai Bomba
a1bvv7rdyeqamt5p2lujpf8yw9vsoci
Wikikamus:ja/橋
4
119789
344275
2026-05-25T13:01:38Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Jambatan'
344275
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Jambatan
edfzuzceupt6h1js5kwem359bkw4miu
Wikikamus:ja/山
4
119790
344276
2026-05-25T13:02:11Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Gunung'
344276
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Gunung
tj639w8w4n5t27enb7efy34dqn7xgkt
Wikikamus:ja/寝室
4
119791
344277
2026-05-25T13:02:53Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Bilik tidur'
344277
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Bilik tidur
9bz2h9tgn3eau17pcher1jub359rgd1
Wikikamus:ja/バスルーム
4
119792
344278
2026-05-25T13:03:16Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Bilik mandi'
344278
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Bilik mandi
sb2n0ggxk49tgnmnhplehxdzjcavc8a
Wikikamus:ja/モスク
4
119793
344279
2026-05-25T13:04:32Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Masjid'
344279
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Masjid
4ywvg8vrzjp8vijop9ga0cil2ccy3tx
Wikikamus:ja/トラック
4
119794
344281
2026-05-25T13:05:30Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Trak lori'
344281
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Trak lori
obm1agd35903vypzr682wcnk2y1fym9
Wikikamus:ja/携帯電話の充電器
4
119795
344282
2026-05-25T13:05:58Z
Ssante10
10156
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Pengecas Telefon'
344282
wikitext
text/x-wiki
==Bahasa {{bahasa|ja}}==
===Kata nama===
{{inti|ja|kata nama}}
# Pengecas Telefon
11didjnze04m4pqpybmr2xk37sr6b51
Wikikamus:en/boulangerie
4
119796
344297
2026-05-25T14:02:18Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # Kedai roti gaya [[Perancis]]. ===Etimologi=== {{ety|en|:bor|fr:boulangerie|text=+|tree=1}} ===Sebutan=== * {{IPA|en|/buˈlɑ̃ʒɚˌɹi/}} {{C|en|Kedai}}'
344297
wikitext
text/x-wiki
==Bahasa {{bahasa|en}}==
===Kata nama===
{{inti|en|kata nama}}
# Kedai roti gaya [[Perancis]].
===Etimologi===
{{ety|en|:bor|fr:boulangerie|text=+|tree=1}}
===Sebutan===
* {{IPA|en|/buˈlɑ̃ʒɚˌɹi/}}
{{C|en|Kedai}}
svaxl9th639b5s2s7c0x00gsn0oc9fk
344298
344297
2026-05-25T14:02:36Z
PeaceSeekers
3334
344298
wikitext
text/x-wiki
==Bahasa {{bahasa|en}}==
===Kata nama===
{{inti|en|kata nama}}
# Kedai roti gaya [[Perancis]].
===Etimologi===
{{etymon|en|:bor|fr:boulangerie|text=+|tree=1}}
===Sebutan===
* {{IPA|en|/buˈlɑ̃ʒɚˌɹi/}}
{{C|en|Kedai}}
kj5m9cdkr87noyoadp5ugbsfmlo0nso
boulangerie
0
119797
344299
2026-05-25T14:03:20Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '{{wt:en/{{PAGENAME}}}}'
344299
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
344307
344299
2026-05-25T14:10:45Z
PEACESEEKERS-BOT
10590
Tambah bahagian fr ([[WT:BOT|bot]])
344307
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}== Perancis ==
{{wt:fr/{{PAGENAME}}}}
n4uofrhzht7l5jt8ar1clffhjzhnrtw
344309
344307
2026-05-25T14:14:15Z
PeaceSeekers
3334
344309
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
{{wt:fr/{{PAGENAME}}}}
1x5fst40dxo38mzxkri668hsn9gicug
Wikikamus:fr/boulangerie
4
119798
344301
2026-05-25T14:05:34Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== {{wp|fr:}} [[Fail:Our_boulangerie_(16095492470).jpg|thumb|250x250px|boulangerie]] ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # kedai roti === Etimologi === {{ety|fr|:af|boulanger|-erie}} From {{af|fr|boulanger|-erie}}. === Sebutan === * {{fr-IPA}} * {{audio|fr|Fr-boulangerie.ogg}} * {{audio|fr|LL-Q150 (fra)-Benoît Prieur-boulangerie.wav|a=<<France>> (<<Saint-Maurice-de-Beynost>>)}...'
344301
wikitext
text/x-wiki
==Bahasa {{bahasa|fr}}==
{{wp|fr:}}
[[Fail:Our_boulangerie_(16095492470).jpg|thumb|250x250px|boulangerie]]
===Kata nama===
{{inti|fr|kata nama}}
# kedai roti
=== Etimologi ===
{{ety|fr|:af|boulanger|-erie}} From {{af|fr|boulanger|-erie}}.
=== Sebutan ===
* {{fr-IPA}}
* {{audio|fr|Fr-boulangerie.ogg}}
* {{audio|fr|LL-Q150 (fra)-Benoît Prieur-boulangerie.wav|a=<<France>> (<<Saint-Maurice-de-Beynost>>)}}
* {{audio|fr|LL-Q150 (fra)-Lepticed7-boulangerie.wav|a=<<France>> (<<Toulouse>>)}}
* {{audio|fr|LL-Q150 (fra)-LoquaxFR-boulangerie.wav|a=<<France>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-boulangerie.wav|a=<<France>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-WikiLucas00-boulangerie.wav|a=<<France>> (<<Lyon>>)}}
{{C|fr|Kedai|Kek dan pastri}}
dinlqcxx9sfba5sg1maxxtrqfv1g24y
Wikikamus:fr/cargo
4
119799
344302
2026-05-25T14:08:28Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # [[kapal]] pembawa [[kargo]] ===Etimologi=== {{ety|fr|:bor|en:cargo}} {{bor+|fr|en|cargo}}. ===Sebutan=== * {{fr-IPA}} * {{audio|fr|LL-Q150 (fra)-Poslovitch-cargo.wav|a=<<Perancis>> (<<Vosges>>)}} * {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-cargo.wav|a=<<Perancis>> (<<Somain>>)}}'
344302
wikitext
text/x-wiki
==Bahasa {{bahasa|fr}}==
===Kata nama===
{{inti|fr|kata nama}}
# [[kapal]] pembawa [[kargo]]
===Etimologi===
{{ety|fr|:bor|en:cargo}}
{{bor+|fr|en|cargo}}.
===Sebutan===
* {{fr-IPA}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-cargo.wav|a=<<Perancis>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-cargo.wav|a=<<Perancis>> (<<Somain>>)}}
si1vhykfj2g8ip15f8v9zcx74ew482r
344303
344302
2026-05-25T14:08:42Z
PeaceSeekers
3334
344303
wikitext
text/x-wiki
==Bahasa {{bahasa|fr}}==
===Kata nama===
{{inti|fr|kata nama}}
# [[kapal]] pembawa [[kargo]]
===Etimologi===
{{etymon|fr|:bor|en:cargo}}
{{bor+|fr|en|cargo}}.
===Sebutan===
* {{fr-IPA}}
* {{audio|fr|LL-Q150 (fra)-Poslovitch-cargo.wav|a=<<Perancis>> (<<Vosges>>)}}
* {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-cargo.wav|a=<<Perancis>> (<<Somain>>)}}
9d2m5sv1hhmlqm0n2bw31l2qxxq27pl
cargo
0
119800
344306
2026-05-25T14:10:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:fr ([[WT:BOT|bot]])
344306
wikitext
text/x-wiki
{{wt:fr/{{PAGENAME}}}}
nupms6fyiw229y8y852m3lrntv5cyzs
344376
344306
2026-05-25T14:33:59Z
PEACESEEKERS-BOT
10590
Tambah bahagian en ([[WT:BOT|bot]])
344376
wikitext
text/x-wiki
{{wt:fr/{{PAGENAME}}}}{{wt:en/{{PAGENAME}}}}
gah7hwhjeko2aedrp63av3v9qrza711
344377
344376
2026-05-25T14:35:10Z
PeaceSeekers
3334
344377
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
{{wt:fr/{{PAGENAME}}}}
1x5fst40dxo38mzxkri668hsn9gicug
ad hoc
0
119801
344310
2026-05-25T14:15:52Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344310
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
agelast
0
119802
344311
2026-05-25T14:16:53Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344311
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
aleatory
0
119803
344314
2026-05-25T14:17:54Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344314
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
balloon
0
119804
344315
2026-05-25T14:18:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344315
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
beatific
0
119805
344316
2026-05-25T14:19:56Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344316
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
brush
0
119806
344317
2026-05-25T14:20:57Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344317
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
buy
0
119807
344318
2026-05-25T14:21:58Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344318
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
cadge
0
119808
344319
2026-05-25T14:22:59Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344319
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
candor
0
119809
344320
2026-05-25T14:24:00Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344320
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
ceiling
0
119810
344321
2026-05-25T14:24:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344321
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
chopstick
0
119811
344322
2026-05-25T14:24:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344322
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
clandestine
0
119812
344323
2026-05-25T14:25:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344323
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
crying
0
119813
344324
2026-05-25T14:25:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344324
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
crystalline
0
119814
344325
2026-05-25T14:25:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344325
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
dross
0
119815
344326
2026-05-25T14:25:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344326
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
eats
0
119816
344327
2026-05-25T14:25:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344327
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
effulgent
0
119817
344328
2026-05-25T14:25:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344328
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
eidolon
0
119818
344329
2026-05-25T14:26:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344329
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
elephant
0
119819
344330
2026-05-25T14:26:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344330
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
embellish
0
119820
344331
2026-05-25T14:26:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344331
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
equanimous
0
119821
344332
2026-05-25T14:26:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344332
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
eraser
0
119822
344333
2026-05-25T14:26:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344333
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
ethereal
0
119823
344334
2026-05-25T14:26:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344334
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
eudemonic
0
119824
344335
2026-05-25T14:27:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344335
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
exhilarate
0
119825
344336
2026-05-25T14:27:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344336
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
felicitate
0
119826
344337
2026-05-25T14:27:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344337
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
fiscal
0
119827
344338
2026-05-25T14:27:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344338
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
flexible
0
119828
344339
2026-05-25T14:27:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344339
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
fortitude
0
119829
344340
2026-05-25T14:27:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344340
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
ice
0
119830
344341
2026-05-25T14:28:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344341
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
interpolate
0
119831
344342
2026-05-25T14:28:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344342
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
juvenescent
0
119832
344343
2026-05-25T14:28:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344343
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
lock
0
119833
344344
2026-05-25T14:28:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344344
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
loudly
0
119834
344345
2026-05-25T14:28:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344345
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
lumberjack
0
119835
344346
2026-05-25T14:28:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344346
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
many
0
119836
344347
2026-05-25T14:29:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344347
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
mea culpa
0
119837
344348
2026-05-25T14:29:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344348
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
muzz
0
119838
344349
2026-05-25T14:29:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344349
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
oblivion
0
119839
344350
2026-05-25T14:29:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344350
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
observe
0
119840
344351
2026-05-25T14:29:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344351
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
paean
0
119841
344352
2026-05-25T14:29:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344352
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
perspicacious
0
119842
344353
2026-05-25T14:30:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344353
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
pizzetta
0
119843
344354
2026-05-25T14:30:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344354
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
prescind
0
119844
344355
2026-05-25T14:30:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344355
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
purify
0
119845
344356
2026-05-25T14:30:36Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344356
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
rabbit
0
119846
344357
2026-05-25T14:30:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344357
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
rogue
0
119847
344358
2026-05-25T14:30:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344358
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
sheep
0
119848
344359
2026-05-25T14:31:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344359
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
solace
0
119849
344360
2026-05-25T14:31:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344360
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
spiel
0
119850
344362
2026-05-25T14:31:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344362
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
stapler
0
119851
344363
2026-05-25T14:31:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344363
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
stone
0
119852
344364
2026-05-25T14:31:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344364
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
Sun
0
119853
344365
2026-05-25T14:31:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344365
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
swim
0
119854
344366
2026-05-25T14:32:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344366
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
television
0
119855
344367
2026-05-25T14:32:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344367
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
traffic
0
119856
344368
2026-05-25T14:32:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344368
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
triumvirate
0
119857
344369
2026-05-25T14:32:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344369
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
tyre
0
119858
344370
2026-05-25T14:32:45Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344370
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
undulate
0
119859
344371
2026-05-25T14:32:55Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344371
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
veracity
0
119860
344372
2026-05-25T14:33:05Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344372
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
working
0
119861
344373
2026-05-25T14:33:15Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344373
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
xylography
0
119862
344374
2026-05-25T14:33:25Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344374
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
zany
0
119863
344375
2026-05-25T14:33:35Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344375
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8
Modul:roa-verb/style.css
828
119864
344386
2026-05-25T23:53:50Z
Hakimi97
2668
Mencipta laman baru dengan kandungan '/* This supplies CSS specs, especially palettized colors (i.e. supporting both light and dark mode) for several Romance-language verb tables, as well as verb tables in other languages with a similar structure (Ancient Greek and Georgian, for two). Be careful when changing this as it will affect several languages at once. */ .roa-footnote-section { /* The footnote section when attached to a larger table. */ background: var(--wikt-palette-l...'
344386
sanitized-css
text/css
/* This supplies CSS specs, especially palettized colors (i.e. supporting both
light and dark mode) for several Romance-language verb tables, as well as
verb tables in other languages with a similar structure (Ancient Greek and
Georgian, for two). Be careful when changing this as it will affect several
languages at once.
*/
.roa-footnote-section {
/* The footnote section when attached to a larger table. */
background: var(--wikt-palette-lightblue, #d9ebff);
}
.roa-footnote-outer-div {
/* The footnote outer div when separate and left-aligned. */
text-align: left;
background: var(--wikt-palette-lightblue, #d9ebff);
}
.roa-footnote-inner-div {
display: inline-block;
text-align: left;
padding-left: 1em;
padding-right: 1em;
}
.roa-red-superscript {
color: var(--wikt-palette-red, red);
}
.roa-inflection-table {
background: var(--wikt-palette-grey-1, #f0f0f0);
text-align: center;
width: 100%;
border-collapse: collapse;
}
.roa-inflection-table th, .roa-inflection-table td {
margin: 0;
border: 2px solid var(--wikt-palette-white, #ffffff);
}
.roa-nonfinite-header {
background: var(--wikt-palette-yellow, #e2e4c0);
}
.roa-person-number-header {
background: var(--wikt-palette-grey-4, #cfcfcf);
}
.roa-native-person-number-header {
background: var(--wikt-palette-grey-2, #ececec);
width: 12.5%;
}
.roa-finite-header {
background:var(--wikt-palette-grey-2, #ececec);
height: 3em;
}
.roa-compound-row {
/* A row replacing one set of tense/aspect/mood combination, specifying to use an auxiliary + past participle */
background: var(--wikt-palette-grey-3, #dedede);
}
.roa-indicative-left-rail {
background:var(--wikt-palette-blue-4, #c0cfe4);
}
.roa-conditional-left-rail {
background:var(--wikt-palette-red-4, #c0e4c0);
}
.roa-subjunctive-left-rail {
background:var(--wikt-palette-green-4, #c0e4c0);
}
.roa-imperative-left-rail {
background:var(--wikt-palette-amber-4, #e4d4c0);
}
/* Currently used only for Occitan to indicate a semi-obsolete form. */
.roa-second-conditional-left-rail {
background:var(--wikt-palette-red-5, #f4c2c2);
}
.roa-combined-with-infinitive {
background:var(--wikt-palette-blue-4, #c0cfe4);
}
.roa-combined-with-gerund {
background:var(--wikt-palette-yellow-4, #d0cfa4);
}
.roa-combined-with-imperative {
background:var(--wikt-palette-orange, #f2caa4);
}
ehnemznreho0v79wnq2jroxpq7we90e
Wikikamus:id/anjlok
4
119865
344411
2026-05-26T05:22:34Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # [[jatuh]] # [[terjun]] # bertambah [[buruk]]'
344411
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata kerja===
{{inti|id|kata kerja}}
# [[jatuh]]
# [[terjun]]
# bertambah [[buruk]]
l0tr66caf6mo2u90cbwlawlbuu7brep
Wikikamus:id/APBN
4
119866
344412
2026-05-26T05:25:19Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # {{lb|id|kewangan|pemerintahan}} {{initialism of|id|[[anggaran pendapatan dan belanja negara]]}}}}'
344412
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# {{lb|id|kewangan|pemerintahan}} {{initialism of|id|[[anggaran pendapatan dan belanja negara]]}}}}
3te889rhm6kk75du59bl9zhdjoyhd6s
344413
344412
2026-05-26T05:25:33Z
PeaceSeekers
3334
344413
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# {{lb|id|kewangan|pemerintahan}} {{initialism of|id|[[anggaran pendapatan dan belanja negara]]}}
1922qa3z8gq1gpa13umce67tw2hde60
Wikikamus:ko/안녕히 계세요
4
119867
344414
2026-05-26T06:30:18Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Selamat tinggal (Jika anda yang pergi, dan tuan rumah yang tinggal).'
344414
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Selamat tinggal (Jika anda yang pergi, dan tuan rumah yang tinggal).
4r79ufloprrmkoe8shoa24lukx19nr4
Wikikamus:ko/실례합니다
4
119868
344415
2026-05-26T06:31:36Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Tumpang lalu / Minta tumpang tanya.'
344415
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Tumpang lalu / Minta tumpang tanya.
ghhc6hm6txscn7nvey3wtaast67seq5
Wikikamus:ko/이거 얼마예요?
4
119869
344416
2026-05-26T06:32:22Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Berapa harga ini?'
344416
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Berapa harga ini?
568kt8qr6w2lokkbfvzykdagmt5lem6
Wikikamus:ko/화장실이 어디예요?
4
119870
344417
2026-05-26T06:33:21Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Di manakah tandas?'
344417
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Di manakah tandas?
7q1biffuvktgkr1cgacb5vq12ste07q
Wikikamus:ko/도와주세요.
4
119871
344418
2026-05-26T06:34:43Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Tolong bantu saya.'
344418
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Tolong bantu saya.
tomrig5lyahy4tb464un41kuk7he1af
Wikikamus:ko/이름이 뭐예요?
4
119872
344419
2026-05-26T06:35:20Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Siapa nama anda?'
344419
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Siapa nama anda?
nqwrirtlxky3sed4q4wawvzbq94iedt
Wikikamus:ko/어디에서 오셨어요?
4
119873
344420
2026-05-26T06:37:11Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Dari mana anda datang?'
344420
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Dari mana anda datang?
tplg9lb4w41sw0dw5hndsoocneukka1
Wikikamus:ko/이해했어요?
4
119874
344421
2026-05-26T06:37:51Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Adakah anda faham?'
344421
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Adakah anda faham?
qqyg91ru1xdsbk523b5kom9xy3prqe7
Wikikamus:ko/모르겠어요.
4
119875
344422
2026-05-26T06:38:39Z
Izzatfikry99
10597
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Frasa=== {{inti|{{safesubst:ROOTPAGENAME}}|frasa}} # Saya tidak tahu.'
344422
wikitext
text/x-wiki
==Bahasa {{bahasa|ko}}==
===Frasa===
{{inti|ko|frasa}}
# Saya tidak tahu.
d5jqfci9vxopzju0scgc7oqdw7yqdfd
Wikikamus:id/eksternal
4
119876
344423
2026-05-26T06:39:42Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata sifat=== {{inti|{{safesubst:ROOTPAGENAME}}|kata sifat}} # [[luaran]] ===Etimologi=== {{bor+|id|en|external}}, daripada {{der|id|la-med|externus||luaran}}, {{m|la|[[exter]]/[[exterus]]||di luar}}. ===Sebutan=== * {{id-pr|èks.ter.nal}}'
344423
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata sifat===
{{inti|id|kata sifat}}
# [[luaran]]
===Etimologi===
{{bor+|id|en|external}}, daripada {{der|id|la-med|externus||luaran}}, {{m|la|[[exter]]/[[exterus]]||di luar}}.
===Sebutan===
* {{id-pr|èks.ter.nal}}
5r5tzwmojirt6txs0vtttwgy622nns7
Wikikamus:id/WIB
4
119877
344424
2026-05-26T06:45:07Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama khas=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama khas}} # {{abbreviation of|id|Waktu Indonesia Barat}} #: {{cot|id|WIT|WITA}} {{C|id|Zon waktu}}'
344424
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama khas===
{{inti|id|kata nama khas}}
# {{abbreviation of|id|Waktu Indonesia Barat}}
#: {{cot|id|WIT|WITA}}
{{C|id|Zon waktu}}
arqxqfiud9xy93z74k6vyhprr6dj7pv
Wikikamus:id/WIT
4
119878
344425
2026-05-26T06:45:59Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|id}}== ===Kata nama khas=== {{inti|id|kata nama khas}} # {{abbreviation of|id|Waktu Indonesia Timur}} #: {{cot|id|WIB|WITA}} {{C|id|Zon waktu}}'
344425
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama khas===
{{inti|id|kata nama khas}}
# {{abbreviation of|id|Waktu Indonesia Timur}}
#: {{cot|id|WIB|WITA}}
{{C|id|Zon waktu}}
ox8co1241y1cots7pu5x09fkkp7rhfi
Wikikamus:id/WITA
4
119879
344426
2026-05-26T06:47:07Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|id}}== ===Kata nama khas=== {{inti|id|kata nama khas}} # {{abbreviation of|id|Waktu Indonesia Tengah}} #: {{cot|id|WIB|WIT}} {{C|id|Zon waktu}}'
344426
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama khas===
{{inti|id|kata nama khas}}
# {{abbreviation of|id|Waktu Indonesia Tengah}}
#: {{cot|id|WIB|WIT}}
{{C|id|Zon waktu}}
mh5w3g2p9g14x01aoen85yd8rs7xqr8
Wikikamus:id/tensi
4
119880
344427
2026-05-26T06:52:04Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # {{label|1={{safesubst:ROOTPAGENAME}}|2=perubatan|3=}} [[tekanan darah]] ===Etimologi=== Daripada {{bor|id|nl|tensie|t=tekanan}}, daripada {{der|id|fr|tension|t=tekanan}}, daripada {{der|id|frm|tension}}, daripada {{der|id|la|tensiō|tensiō, tensiōnem}}. ===Sebutan=== {{id-pr|tènsi}}'
344427
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# {{label|1=id|2=perubatan|3=}} [[tekanan darah]]
===Etimologi===
Daripada {{bor|id|nl|tensie|t=tekanan}}, daripada {{der|id|fr|tension|t=tekanan}}, daripada {{der|id|frm|tension}}, daripada {{der|id|la|tensiō|tensiō, tensiōnem}}.
===Sebutan===
{{id-pr|tènsi}}
duk1qxwvf8g82c0nerhe2uaoto4w066
Wikikamus:id/militer
4
119881
344428
2026-05-26T06:57:54Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # [[tentera]] # [[ketenteraan]] ===Etimologi=== Daripada {{bor|id|nl|militair}}, daripada {{der|id|frm|militaire}}, daripada {{der|id|la|mīlitāris||berkenaan tentera perang}}, from {{m|la|mīles||tentera}}. ===Sebutan=== * {{IPA|id|[miˈli.tɛr]}} * {{hyphenation|id|mi|li|tèr}}'
344428
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# [[tentera]]
# [[ketenteraan]]
===Etimologi===
Daripada {{bor|id|nl|militair}}, daripada {{der|id|frm|militaire}}, daripada {{der|id|la|mīlitāris||berkenaan tentera perang}}, from {{m|la|mīles||tentera}}.
===Sebutan===
* {{IPA|id|[miˈli.tɛr]}}
* {{hyphenation|id|mi|li|tèr}}
dyt30hy2ql0p5l8vosqe4yt8sf6zj0l
Wikikamus:fr/militer
4
119882
344429
2026-05-26T07:00:59Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata kerja=== {{inti|{{safesubst:ROOTPAGENAME}}|kata kerja}} # mengerahkan [[tentera]] # melakukan kempen [[ketenteraan]] ===Sebutan=== * {{audio|fr|LL-Q150 (fra)-Lyokoï-militer.wav|a=<<Perancis>> (<<Lyon>>)}} * {{audio|fr|LL-Q150 (fra)-WikiLucas00-militer.wav|a=<<Perancis>> (<<Lyon>>)}} * {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-militer.wav|a=<<Perancis>> (<<Somain>>)}} {{C|fr|Ke...'
344429
wikitext
text/x-wiki
==Bahasa {{bahasa|fr}}==
===Kata kerja===
{{inti|fr|kata kerja}}
# mengerahkan [[tentera]]
# melakukan kempen [[ketenteraan]]
===Sebutan===
* {{audio|fr|LL-Q150 (fra)-Lyokoï-militer.wav|a=<<Perancis>> (<<Lyon>>)}}
* {{audio|fr|LL-Q150 (fra)-WikiLucas00-militer.wav|a=<<Perancis>> (<<Lyon>>)}}
* {{audio|fr|LL-Q150 (fra)-Jérémy-Günther-Heinz Jähnick-militer.wav|a=<<Perancis>> (<<Somain>>)}}
{{C|fr|Ketenteraan}}
ar3sgh2ucngqcx4d89vz62e9g3r4eon
Wikikamus:ms/Fiji
4
119883
344430
2026-05-26T07:04:56Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama khas=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama khas}} # {{place|ms|negara/dan/kepulauan|r/Melanesia|di|cont/Oceania|caplc=Suva}}.'
344430
wikitext
text/x-wiki
==Bahasa {{bahasa|ms}}==
===Kata nama khas===
{{inti|ms|kata nama khas}}
# {{place|ms|negara/dan/kepulauan|r/Melanesia|di|cont/Oceania|caplc=Suva}}.
td4dhksiozohcwgcl6n7we1gpek2ef3
Wikikamus:en/Fiji
4
119884
344431
2026-05-26T07:09:36Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama khas=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama khas}} # {{tcl|en|Fiji}} ===Etimologi=== {{bor+|en|to|Fisi}} (asalnya disebut {{IPA|to|[ˈfit͡ʃi]}}) yang sendirinya pinjaman daripada {{der|en|fj|Viti}}, daripada bahasa Pasifik Tengah Purba ''*viti'' ‘timur, matahari terbit’. Ejaan Inggeris ''Fiji'' dipopularkan oleh transkripsi Tonga abad ke-18 oleh Kapten James Cook. ===Sebutan...'
344431
wikitext
text/x-wiki
==Bahasa {{bahasa|en}}==
===Kata nama khas===
{{inti|en|kata nama khas}}
# {{tcl|en|Fiji}}
===Etimologi===
{{bor+|en|to|Fisi}} (asalnya disebut {{IPA|to|[ˈfit͡ʃi]}}) yang sendirinya pinjaman daripada {{der|en|fj|Viti}}, daripada bahasa Pasifik Tengah Purba ''*viti'' ‘timur, matahari terbit’. Ejaan Inggeris ''Fiji'' dipopularkan oleh transkripsi Tonga abad ke-18 oleh Kapten James Cook.
===Sebutan===
* {{enPR|fēʹjē|fējēʹ|a=UK}}, {{IPA|en|/ˈfiːdʒiː/|/fiːˈdʒiː/}}
** {{audio|en|LL-Q1860 (eng)-Soundguys-Fiji.wav|a=UK}}
* {{IPA|en|/ˈfiːdʒiː/|a=AS}}
** {{audio|en|en-us-Fiji.ogg|a=AS}}
* {{IPA|en|/fiːˈdʒiː/|a=AU}}
* {{rhymes|en|iːdʒi|s=2}}
mxs5k42zlskkij5hdimkl89xwuw4k20
Wikikamus:id/pengamat
4
119885
344432
2026-05-26T07:12:28Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} #[[pemerhati]] ===Etimologi=== Daripada {{pre|id|peng|amat}}. ===Sebutan=== * {{id-pr}}'
344432
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
#[[pemerhati]]
===Etimologi===
Daripada {{pre|id|peng|amat}}.
===Sebutan===
* {{id-pr}}
fg98xx55yhmls109zjoa6o6exhu2e37
Wikikamus:id/Bareskrim
4
119886
344433
2026-05-26T07:18:33Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama khas=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama khas}} # {{lb|id|polis}} {{sylabbr of|id|[[badan]] [[reserse]] [[kriminal]]|t=badan siasatan jenayah}}'
344433
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama khas===
{{inti|id|kata nama khas}}
# {{lb|id|polis}} {{sylabbr of|id|[[badan]] [[reserse]] [[kriminal]]|t=badan siasatan jenayah}}
dq4njjj8t2a7udoi8vcy13xay2z7m3r
Wikikamus:id/pensiun
4
119887
344434
2026-05-26T07:24:21Z
PeaceSeekers
3334
Mencipta laman baru dengan kandungan '==Bahasa {{bahasa|{{safesubst:ROOTPAGENAME}}}}== ===Kata nama=== {{inti|{{safesubst:ROOTPAGENAME}}|kata nama}} # [[pencen]] # [[persaraan]] ===Etimologi=== Daripada {{inh|id|ms|pensiun}}, daripada {{der|id|nl|pensioen}}, daripada {{der|id|dum|pensioen}}, daripada {{der|id|fro|pension||bayaran, sewa}}, daripada {{der|id|la|pensio||bayaran, sewa}}, daripada {{m|la|pensus}}, bentuk partisipel lampau {{m|la|pendo|pendere|timbang, bayar}}. ===Sebutan=== *...'
344434
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# [[pencen]]
# [[persaraan]]
===Etimologi===
Daripada {{inh|id|ms|pensiun}}, daripada {{der|id|nl|pensioen}}, daripada {{der|id|dum|pensioen}}, daripada {{der|id|fro|pension||bayaran, sewa}}, daripada {{der|id|la|pensio||bayaran, sewa}}, daripada {{m|la|pensus}}, bentuk partisipel lampau {{m|la|pendo|pendere|timbang, bayar}}.
===Sebutan===
* {{IPA|id|[pɛnˈsiʊn]}}
* {{hyphenation|id|pèn|si|un}}
j6gh9fou2c5c56mojy1u0u65vwbfdeg
344435
344434
2026-05-26T07:29:05Z
PeaceSeekers
3334
344435
wikitext
text/x-wiki
==Bahasa {{bahasa|id}}==
===Kata nama===
{{inti|id|kata nama}}
# [[pencen]]
# [[persaraan]]
===Kata kerja===
{{inti|id|kata kerja}}
# [[pencen|berpencen]], [[bersara]]
===Etimologi===
Daripada {{inh|id|ms|pensiun}}, daripada {{der|id|nl|pensioen}}, daripada {{der|id|dum|pensioen}}, daripada {{der|id|fro|pension||bayaran, sewa}}, daripada {{der|id|la|pensio||bayaran, sewa}}, daripada {{m|la|pensus}}, bentuk partisipel lampau {{m|la|pendo|pendere|timbang, bayar}}.
===Sebutan===
* {{IPA|id|[pɛnˈsiʊn]}}
* {{hyphenation|id|pèn|si|un}}
{{C|id|Kewangan}}
2oldye5joc38g464bgjs3vokxojag31
militer
0
119888
344436
2026-05-26T07:46:22Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:fr ([[WT:BOT|bot]])
344436
wikitext
text/x-wiki
{{wt:fr/{{PAGENAME}}}}
nupms6fyiw229y8y852m3lrntv5cyzs
344446
344436
2026-05-26T07:48:55Z
PEACESEEKERS-BOT
10590
Tambah bahagian id ([[WT:BOT|bot]])
344446
wikitext
text/x-wiki
{{wt:fr/{{PAGENAME}}}}{{wt:id/{{PAGENAME}}}}
jpiembd9b7p3v8xufzyaiy41dmsq9c0
344447
344446
2026-05-26T07:49:55Z
PeaceSeekers
3334
344447
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
{{wt:fr/{{PAGENAME}}}}
p1lp0ghe542g08qnwxlayrfmxkluqo0
anjlok
0
119889
344437
2026-05-26T07:46:46Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344437
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
APBN
0
119890
344438
2026-05-26T07:46:56Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344438
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
Bareskrim
0
119891
344439
2026-05-26T07:47:06Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344439
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
eksternal
0
119892
344440
2026-05-26T07:47:16Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344440
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
pensiun
0
119893
344441
2026-05-26T07:47:26Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344441
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
tensi
0
119894
344442
2026-05-26T07:47:36Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344442
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
WIB
0
119895
344443
2026-05-26T07:47:46Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344443
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
WIT
0
119896
344444
2026-05-26T07:47:56Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344444
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
WITA
0
119897
344445
2026-05-26T07:48:06Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:id ([[WT:BOT|bot]])
344445
wikitext
text/x-wiki
{{wt:id/{{PAGENAME}}}}
d28yfwupaiv93m3yctmilqnomkiyptr
Fiji
0
119898
344448
2026-05-26T07:54:22Z
PEACESEEKERS-BOT
10590
Cipta laman daripada Wikikamus:en ([[WT:BOT|bot]])
344448
wikitext
text/x-wiki
{{wt:en/{{PAGENAME}}}}
2y33swzmyjj8jr581mnvur6xi1gpqs8