Wîkîferheng kuwiktionary https://ku.wiktionary.org/wiki/Destp%C3%AAk MediaWiki 1.47.0-wmf.10 case-sensitive Medya Taybet Gotûbêj Bikarhêner Gotûbêja bikarhêner Wîkîferheng Gotûbêja Wîkîferhengê Wêne Gotûbêja wêneyî MediaWiki Gotûbêja MediaWiki Şablon Gotûbêja şablonê Alîkarî Gotûbêja alîkariyê Kategorî Gotûbêja kategoriyê Pêvek Gotûbêja pêvekê Nimînok Gotûbêja nimînokê Portal Gotûbêja portalê Tewandin Gotûbêja tewandinê Jinûvesazî Gotûbêja jinûvesaziyê TimedText TimedText talk Modul Gotûbêja modulê Event Event talk reş 0 3121 6241660 6233912 2026-07-11T20:22:57Z Wikihez 7344 [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin 6241660 wikitext text/x-wiki {{bnr-h|res}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{deng|ku|LL-Q36163 (kmr)-Key Mîrza-reş.wav|Deng|Wan}} * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|reş}} [[Wêne:Solid black.svg|thumb|150px|Rengê reş.]] {{rengdêr|ku}} # {{f|ku|reng}} [[reng|Reng]]ê ji hemiyan [[tarî]]tir, [[wek]] rengê [[rejî|rejiyê]]. #: {{panela rengê|000000}} #* {{jêder|ku|jêgirtin=-Tu jî mîna Fêdkayê min esmer î, çevreş, porê te '''reş'''.|{{Jêgirtin/Frîda Hecî Cewarî/Bîranînên Min}}}} #* {{jêder|ku|jêgirtin=Digel ku emrê wî hê sî û pênc bû jî tayekî '''reş''' di porê wî de nemabû.|{{Jêgirtin/Firat Cewerî/Kevoka Spî/1996}}}} #* {{jêder|ku|jêgirtin=Û ew libasêd '''reş''' heta şeş mehan û yaxo salekê li ser ehlê (xizmê) meyyitî dimînin. Ew ehlê meyyitî heta ji şînê bidernekevin naçine dawet û kêfxweşiyan.|{{jêgirtin/Mele Mehmûdê Bayezîdî/Adat û Rusûmatnameê Ekradiye|r=53}}}} # Ji [[ronahî|ronahiyê]] [[bêpar]]. #: {{hevmane|ku|tarî}} #* {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Saqî ko dêm mehweş bitin<br />Kagul ji şêva '''reş''' bitin<br />Qerqef bila ateş bitin}} #* {{jêder|ku|jêgirtin=(...) mîna tîrekê navdilê Qaçax hingavtin, ling lê lerizîn, ber çavên wî '''reş''' bû (...)|{{Jêgirtin/Sîma Semend/Xezal/1996}}}} # [[temirandî]] #: {{nm|ku|Ka wê çirayê '''reş''' bike.}} # [[mirov|Mirov]]ên [[çerm]]reş yên mîna [[Afrîkî|afrîkiyan]]. #: {{hevmane|ku|çermreş}} #* {{jêder|ku|jêgirtin=Zelamekê req û hişk û '''reş''' hate bi nik wan ve.|{{Jêgirtin/Xelîl Duhokî/Antolojiya Çîroka Nû ya Kurmancên Başûr}}}} # [[bêyom]], [[pirr]] [[xirab]], [[nebaş]] #* {{jêder|ku|jêgirtin=Bextê me '''reş''' e, kezeb birîn e.|{{Jêgirtin/Mehmed Uzun/Siya Evînê/1989}}}} ==== Bi alfabeyên din ==== * {{ku-ar|ڕەش}} * {{ku-kr|рәш}} ==== Herwiha ==== * {{hw|ku|riş||Reşwî}} ==== Hevmane ==== * {{g|ku|siyah}} {{i|tenê [[edebî]]}} * {{g|ku|qere-}} {{i|tenê wek [[pêşgir]]}} ==== Binêre herwiha ==== * {{g|ku|kesk}} * {{g|ku|mor}} * [[pembeyî]], [[pîvazî]] * {{g|ku|pirteqalî}} * {{g|ku|qehweyî}} * {{g|ku|sor}} * {{g|ku|şîn}} * {{g|ku|zer}} ==== Jê ==== {{stûn| * {{mj|lêker}} {{g|ku|reş bûn}} * {{mj|lêker}} {{g|ku|reş kirin}} * {{mj|navdêr}} {{g|ku|reşbûn}} * {{mj|navdêr}} {{g|ku|reşkirin}} * {{mj|rengdêr}} {{g|ku|reşbûyî}} * {{mj|rengdêr}} {{g|ku|reşkirî}} * {{g|ku|reşokî}} * {{g|ku|reşole}} * {{g|ku|reşnivîs}} * {{g|ku|reşmeh}} * {{g|ku|reşname}} * {{g|ku|reşpatî}} * {{g|ku|ripîreş}} }} ==== Etîmolojî ==== Taliyê ji {{ji|ira-pro|ku|*ra(n)ǰ-|w=reng kirin, boyax kirin}}. Hevreha {{hv|ckb|ڕەش}}, {{hv|kho|rraşa|w=ya ku bi rengê tarî}}, {{hv|tly|رش|tr=rəş|w=qehweyiya zelal}}, {{hv|sog|tr=rɣš-|ts=raxš|w={{w|Rexş}}, hespê [[Ristem]]}}, {{hv|fa|رخش|tr=rexş|w=sor}}, {{hv|mzn|رش|tr=raš|w=sor}}. Guherîna maneya rengan di zimanên hindûewropî de diyardeyeke berbelav e. ;{{biçûk|Çavkanî: * {{Cheung|r=314}} }} ==== Bide ber ==== * {{g|ku|reştarî}} * {{g|ku|reşûşîn kirin}} * {{g|ku|reşûşîn}} * {{g|ku|reşpoş}} ==== Bi zaravayên din ==== * {{Z|ckb}}: {{W-|ckb|ڕەش|tr=reş}} * {{Z|sdh}}: {{W-|sdh|siya|sc=Latn}}, {{W-|sdh|siyaw|sc=Latn}} * {{Z|hac}}: {{W-|hac|siyaw|sc=Latn}} * {{Z|zza}}: {{W-|zza|sîya}} ==== Werger ==== {{werger-ser}} * {{Z|ab}}: {{W-|ab|аиқәаҵәа}} * {{Z|ace}}: {{W-|ace|itam}} * {{Z|adt}}: {{W-|adt|waurrunha}} * {{Z|af}}: {{W+|af|swart}} * {{Z|akl}}: {{W-|akl|maitum}} * {{Z|sq}}: {{W+|sq|zi}} * {{Z|de}}: {{W+|de|schwarz}} * {{Z|alt}}: {{W-|alt|кара}} * {{Z|am}}: {{W-|am|ጥቁር}} * {{Z|ani}}: {{W-|ani|бечӏедир}} * {{Z|rme}}: {{W-|rme|kalo}} * Apaçî: *: {{Z|apw}}: {{W-|apw|diłhił}} * {{Z|an}}: {{W-|an|negro}} * {{Z|rup}}: {{W-|rup|negru}}, {{W+|rup|laiu}} * {{Z|aer}}: {{W-|aer|artepe}} * {{Z|as}}: {{W-|as|ক‌’লা}}, {{W-|as|কুলা}} * {{Z|ast}}: {{W+|ast|ñegru}}, {{W+|ast|negru}}, {{W+|ast|prietu}} * {{Z|cni}}: {{W-|cni|cheenkari}}, {{W-|cni|kisaari}} * {{Z|atj}}: {{W-|atj|makatewaw}} * {{Z|aot}}: {{W-|aot|pinak}} * {{Z|av}}: {{W-|av|чӏегӏера}}, {{W-|av|чӏегӏераб}} * {{Z|ay}}: {{W-|ay|ch’iyara}} * {{Z|az}}: {{W+|az|qara}} * {{Z|ban}}: {{W-|ban|badeng}} * {{Z|bjn}}: {{W-|bjn|hirang}} * {{Z|eu}}: {{W-|eu|beltz}} * {{Z|ba}}: {{W-|ba|ҡара}} * {{Z|bbl}}: {{W-|bbl|ჺარჭინ}} * {{Z|be}}: {{W+|be|чо́рны}} * {{Z|bn}}: {{W+|bn|কালো}}, {{W+|bn|কাল}} * {{Z|br}}: {{W+|br|du}} * {{Z|bug}}: {{W-|bug|ma-lotoŋ}} * {{Z|mbb}}: {{W-|mbb|me'item}} * {{Z|bg}}: {{W+|bg|че́рен}} * {{Z|my}}: {{W+|my|နက်}}, {{W+|my|မည်း}} * {{Z|bua}}: {{W-|bua|хара}} * {{Z|kac}}: {{W-|kac|chyang}} * {{Z|dz}}: {{W-|dz|གནགཔོ}} * {{Z|ccc}}: {{W-|ccc|kosewa}} * {{Z|ce}}: {{W-|ce|ӏаьржа}} * {{Z|cs}}: {{W+|cs|černý}} * {{Z|chr}}: {{W-|chr|ᎬᎿᎨ}} * {{Z|cic}}: {{W-|cic|losa'}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|黑|tr=hak1}}, {{W-|yue|黑色|tr=haak1 sik1, hak1 sik1}} *: {{Z|dng}}: {{W-|dng|хи}} *: {{Z|cmn}}: {{W+|cmn|黑|tr=hēi}}, {{W+|cmn|黑色|tr=hēisè}}, {{W+|cmn|烏色|tr=wūsè}} *: {{Z|cdo}}: {{W-|cdo|烏|tr=ŭ}} *: {{Z|nan}}: {{W-|nan|黑|tr=hek}}, {{W-|nan|黑色|tr=hek-sek}}, {{W+|nan|烏色|tr=o͘-siak / o͘-sek}} *: {{Z|wuu}}: {{W-|wuu|黑}} * {{Z|cv}}: {{W-|cv|хура}} * {{Z|chk}}: {{W-|chk|chon}} * {{Z|dlm}}: {{W-|dlm|fosc}} * {{Z|da}}: {{W+|da|sort}} * {{Z|dgr}}: {{W-|dgr|dezǫ}} * {{Z|dlg}}: {{W-|dlg|кара}} * {{Z|ovd}}: {{W-|ovd|swart}} * {{Z|id}}: {{W+|id|hitam}} * {{Z|ar}}: {{W+|ar|أَسْوَد|n}}, {{W-|ar|سَوْدَاء|m}}, {{W-|ar|سُود|p}} *: {{Z|arz}}: {{W-|arz|اسود|tr=eswid}} *: {{Z|acw}}: {{W-|acw|أسود|tr=ʾaswad}} *: {{Z|ary}}: {{W-|ary|كحل|tr=kḥal}}, {{W-|ary|سود|tr=swad}} * {{Z|hy}}: {{W-|hy|սև}} * {{Z|myv}}: {{W-|myv|раужо}} * {{Z|eo}}: {{W+|eo|nigra}} * {{Z|et}}: {{W+|et|must}} * {{Z|ett}}: {{W-|ett|𐌑𐌖𐌓𐌉}} * {{Z|eve}}: {{W-|eve|хакарин}} * {{Z|evn}}: {{W-|evn|конңорин}} * {{Z|ee}}: {{W-|ee|yibɔ}} * {{Z|ext}}: {{W-|ext|negru}} * {{Z|fa}}: {{W+|fa|سیاه|tr=siyâh}} * {{Z|fo}}: {{W+|fo|svartur}} * {{Z|fj}}: {{W+|fj|loaloa}} * {{Z|fi}}: {{W+|fi|musta}} * {{Z|fr}}: {{W+|fr|noir}} * {{Z|fur}}: {{W-|fur|neri}} * {{Z|frr}}: *: Föhr: {{W-|frr|suart}} *: Hallig: {{W-|frr|süürt}} *: {{Z|frr}}: {{W-|frr|suurt}} * {{Z|fy}}: {{W+|fy|swart}} * {{Z|gd}}: {{W+|gd|dubh}} * {{Z|gl}}: {{W+|gl|negro}} * {{Z|gdo}}: {{W-|gdo|бечӏер}} * {{Z|gon}}: {{W-|gon|నల్లా|tr=nallā}} * {{Z|gor}}: {{W-|gor|yitomo}} * {{Z|got}}: {{W-|got|𐍃𐍅𐌰𐍂𐍄𐍃}} * {{Z|gu}}: {{W+|gu|કાળું}} * {{Z|ka}}: {{W+|ka|შავი}} * {{Z|ht}}: {{W-|ht|nwa}} * {{Z|hur}}: {{W-|hur|ts'q'éyx̱}} *: {{Z|hur}}: {{W-|hur|tsq'ix}} * {{Z|haw}}: {{W-|haw|ʻeleʻele}} * {{Z|mba}}: {{W-|mba|maitum}} * {{Z|hi}}: {{W+|hi|काला}}, {{W+|hi|कारौ}} * {{Z|hil}}: {{W-|hil|maitum}} * {{Z|mww}}: {{W-|mww|dub}} * {{Z|nl}}: {{W+|nl|zwart}} * {{Z|hop}}: {{W-|hop|qömvi}} * {{Z|ibg}}: {{W-|ibg|ngisit}} * {{Z|he}}: {{W+|he|שחור|tr=shakhór|cuda=שחור \ שָׁחֹר}}, {{W-|he|שחורה|m|tr=sh'khorá|cuda=שחורה \ שְׁחֹרָה}} * {{Z|io}}: {{W+|io|nigra}} * {{Z|ig}}: {{W-|ig|nwa}} * {{Z|ilo}}: {{W-|ilo|nangisit}} * {{Z|ang}}: {{W-|ang|blæc}}, {{W-|ang|sweart}} * {{Z|en}}: {{W+|en|black}} * {{Z|inh}}: {{W-|inh|ӏаьржа}} * {{Z|ia}}: {{W+|ia|nigre}} * {{Z|ill}}: {{W-|ill|maitem}} * {{Z|ga}}: {{W+|ga|dubh}} * {{Z|isd}}: {{W-|isd|ngisit}} * {{Z|ist}}: {{W-|ist|nìgaro}}, {{W-|ist|nìgro}} * {{Z|it}}: {{W+|it|nero}} * {{Z|ium}}: {{W-|ium|jieqv}} * {{Z|is}}: {{W+|is|svartur}} * {{Z|ja}}: {{W+|ja|黒い|tr=くろい, kuroi}}, {{W-|ja|[[黒色]]の|tr=こくしょくの, kokushoku no}} * {{Z|jv}}: {{W+|jv|ireng}}, {{W-|jv|ireŋ}}, {{W-|jv|cemeŋ}}, {{W-|jv|hirěng}} * {{Z|kl}}: {{W+|kl|qernertoq}} * {{Z|xal}}: {{W-|xal|хар}} * {{Z|kn}}: {{W+|kn|ಕಪ್ಪು}} * {{Z|pam}}: {{W-|pam|matuling}} * {{Z|krc}}: {{W-|krc|къара|tr=qara}} * {{Z|csb}}: {{W-|csb|czôrny}} * {{Z|ca}}: {{W+|ca|negre}} * {{Z|zku}}: {{W-|zku|pulyuna}} * {{Z|qu}}: {{W-|qu|yana}} * {{Z|kjj}}: {{W-|kjj|мичӏаь}} * {{Z|ky}}: {{W+|ky|кара}}, {{W-|ky|күңүрт кара}}, {{W+|ky|караңгы}}, {{W+|ky|каралоо}}, {{W+|ky|ушактоо}}, {{W+|ky|жамандоо}}, {{W+|ky|жаманатты кылуу}}, {{W+|ky|жала жабуу}}, {{W+|ky|көө}} * {{Z|kg}}: {{W-|kg|ndombe}} * {{Z|ki}}: {{W-|ki|-irũ}} * {{Z|si}}: {{W+|si|කළු}} * {{Z|koi}}: {{W-|koi|сьӧд}} * {{Z|ko}}: {{W+|ko|검다}}, {{W+|ko|검은}}, {{W+|ko|까맣다}}, {{W-|ko|까만}} * {{Z|kw}}: {{W-|kw|du}} * {{Z|co}}: {{W+|co|neru}} * {{Z|mfe}}: {{W-|mfe|nwar}} * {{Z|kum}}: {{W-|kum|къара|tr=qara}} * {{Z|qui}}: {{W-|qui|shĺpa}} * {{Z|lbj}}: {{W-|lbj|ནག་པོ}} * {{Z|lld}}: {{W-|lld|fosch|n}} * {{Z|lad}}: {{W-|lad|preto}} * {{Z|lkt}}: {{W-|lkt|sápa}} * {{Z|ltg}}: {{W-|ltg|malns}} * {{Z|la}}: {{W+|la|ater}}, {{W+|la|niger}} * {{Z|lv}}: {{W+|lv|melns}} * {{Z|lo}}: {{W-|lo|ດຳ}} * {{Z|lez}}: {{W-|lez|чӏулав}} * {{Z|mhx}}: {{W-|mhx|no, |tr=nòʔ}} * {{Z|ln}}: {{W-|ln|moíndo}} * {{Z|lij}}: {{W-|lij|néigro}} * {{Z|li}}: {{W+|li|zwart}} * {{Z|lt}}: {{W-|lt|júodas}} * {{Z|lmo}}: {{W-|lmo|négher}}, {{W-|lmo|negro}} * {{Z|khb}}: {{W-|khb|ᦡᧄ}} * {{Z|mhn}}: {{W-|mhn|schbòrz}} * {{Z|mad}}: {{W-|mad|celleng}} * {{Z|mak}}: {{W-|mak|le'leng}} * {{Z|mk}}: {{W-|mk|црн}} * {{Z|mg}}: {{W+|mg|mainty}} * {{Z|ml}}: {{W+|ml|കറുപ്പ്}} * {{Z|ms}}: {{W+|ms|hitam}}, {{W+|ms|aswad}}, {{W-|ms|lotong}}, {{W-|ms|lutung}}, {{W-|ms|lutong}} *: {{Z|ms}}: {{W-|ms|هيتم}}, {{W-|ms|اسود}}, {{W-|ms|لوتوڠ}} * {{Z|mt}}: {{W+|mt|iswed|n}}, {{W-|mt|sewda|m}}, {{W-|mt|suwed|p}} * {{Z|mnc}}: {{W-|mnc|ᠰᠠᡥᠠᠯᡳᠶᠠᠨ}}, {{W-|mnc|ᡴᠠᡵᠠ|tr=kara}} * {{Z|gv}}: {{W-|gv|doo}} * {{Z|msk}}: {{W-|msk|maitum}} * {{Z|mi}}: {{W+|mi|mangu}} * {{Z|mrw}}: {{W-|mrw|maitem}}, {{W-|mrw|delem}} * {{Z|mr}}: {{W+|mr|काळा|n}} * {{Z|mrc}}: {{W-|mrc|nilyig}} * {{Z|mop}}: {{W-|mop|bʼox}} * {{Z|hu}}: {{W+|hu|fekete}} * {{Z|egy}}: {{W-egy|km|h=km-m-D3}} * {{Z|lus}}: {{W-|lus|dum}} * {{Z|min}}: {{W-|min|itam}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|хар}} *: Mongolî: {{W-|mn|ᠬᠠᠷ᠎ᠠ}} * {{Z|nfr}}: {{W-|nfr|wɔɔ}} * Nahuatl: *: {{Z|nhn}}: {{W-|nhn|tliltic}} *: Klasîk: {{W-|nci|tliltic}}, {{W-|nci|capotztic}} * {{Z|naq}}: {{W-|naq|ǂnū}} * {{Z|nmb}}: {{W-|nmb|im'ət}} * {{Z|gld}}: {{W-|gld|сахарин}} * {{Z|nap}}: {{W-|nap|niro}} * {{Z|nv}}: {{W-|nv|łizhin}} * {{Z|na}}: {{W+|na|etangang}}, {{W-|na|etañañ}}, {{W-|na|etaŋaŋ}} * {{Z|nxq}}: {{W-|nxq|naq}} * {{Z|nds}}: *: {{Z|nds-de}}: {{W-|nds-de|swart}} * {{Z|ne}}: {{W+|ne|कालो}} * {{Z|nay}}: {{W-|nay|kro:tin}} * {{Z|nia}}: {{W-|nia|a-itö}} * {{Z|nog}}: {{W-|nog|кара}} * {{Z|nuk}}: {{W-|nuk|tupkuk}} * {{Z|nrf}}: {{W-|nrf|nièr|n}}, {{W-|nrf|né|n}}, {{W-|nrf|néthe|m}}, {{W-|nrf|naithe|m}} * {{Z|non}}: {{W-|non|svartr}}, {{W-|non|blakkr}} * {{Z|no}}: {{W+|no|svart}}, {{W+|no|sort}} * {{Z|nwy}}: {{W-|nwy|gahuntee}} * {{Z|ood}}: {{W-|ood|chuk}} * {{Z|oj}}: {{W-|oj|makade-}}, {{W-|oj|makadewaa}}, {{W-|oj|makadewizi}} * {{Z|oc}}: {{W+|oc|negre}} * {{Z|or}}: {{W+|or|କଲା}} * {{Z|om}}: {{W+|om|gurraacha}} * {{Z|os}}: {{W-|os|сау}} * {{Z|ug}}: {{W+|ug|قارا}} * {{Z|uz}}: {{W+|uz|qora}}, {{W+|uz|siyoh}} * {{Z|pag}}: {{W-|pag|deket}} * {{Z|ps}}: {{W+|ps|تور}} * {{Z|pms}}: {{W-|pms|neir}} * {{Z|pjt}}: {{W-|pjt|maṟu}} * {{Z|pl}}: {{W+|pl|czarny}} * {{Z|pt}}: {{W+|pt|preto}}, {{W+|pt|atro}}, {{W+|pt|negro}} * {{Z|pa}}: {{W+|pa|ਕਾਲਾ}} * {{Z|kk}}: {{W+|kk|қара}} * {{Z|cop}}: {{W-|cop|ⲭⲁⲙⲉ}} * {{Z|rap}}: {{W-|rap|kere kere}}, {{W-|rap|uri uri}} * {{Z|rhg}}: {{W-|rhg|hala}} * {{Z|rgn}}: {{W-|rgn|négar}} * {{Z|rm}}: {{W-|rm|nair}} * {{Z|rom}}: {{W-|rom|kalo}} *: {{Z|rmn}}: {{W-|rmn|kalo}} *: {{Z|rml}}: {{W-|rml|kalo}} *: {{Z|rmc}}: {{W-|rmc|kalo}} *: {{Z|rmo}}: {{W-|rmo|kalo}} *: {{Z|rmy}}: {{W-|rmy|kalo}} * {{Z|ro}}: {{W+|ro|negru}} * {{Z|ru}}: {{W+|ru|чёрный}}, {{W+|ru|вороно́й}} * {{Z|str}}: {{W-|str|NEKIX}} * {{Z|se}}: {{W-|se|čáhppes}} * {{Z|sa}}: {{W+|sa|कृष्ण}}, {{W+|sa|काला}} * Sardinian: *: {{Z|sc}}: {{W-|sc|nieddu|n}} *: {{Z|sc}}: {{W-|sc|niéddhu|n}} *: {{Z|sc}}: {{W-|sc|nigheddu|n}} * {{Z|sas}}: {{W-|sas|bidəŋ}} * {{Z|ceb}}: {{W-|ceb|itom}} * {{Z|scn}}: {{W+|scn|nìuru}} * {{Z|sd}}: {{W+|sd|ڪارو}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|цр̑н}} *: Latînî: {{W+|sh|cȓn}} * {{Z|syl}}: {{W-|syl|ꠇꠣꠟꠣ}} * {{Z|cu}}: {{W-|cu|чрьнъ}} * {{Z|sk}}: {{W-|sk|čierny}} * {{Z|sl}}: {{W+|sl|črn}} * {{Z|zlw-slv}}: {{W-|zlw-slv|čǻrnï}} * {{Z|so}}: {{W+|so|madow}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|carny}} *: {{Z|hsb}}: {{W+|hsb|čorny}} * {{Z|es}}: {{W+|es|negro}} * {{Z|su}}: {{W-|su|hideung}} * {{Z|sva}}: {{W-|sva|მეშხე}} * {{Z|sw}}: {{W-|sw|eusi}} * {{Z|ss}}: {{W-|ss|mnyáma}} * {{Z|sv}}: {{W+|sv|svart}} * {{Z|shy}}: {{W-|shy|aberkan}} * {{Z|xsr}}: {{W-|xsr|ནག་པུ|tr=nakpu}} * {{Z|zdj}}: {{W-|zdj|-[[ɗu]]}} * {{Z|sn}}: {{W-|sn|dema}} * {{Z|cjs}}: {{W-|cjs|қара|tr=qara}} * {{Z|tab}}: {{W-|tab|кӏару}} * {{Z|tg}}: {{W+|tg|сиёҳ}} * {{Z|tl}}: {{W+|tl|itim}} * {{Z|ty}}: {{W-|ty|ʻereʻere}} * {{Z|ta}}: {{W+|ta|கருப்பு}} * {{Z|roa-tar}}: {{W-|roa-tar|gnure}} * {{Z|rif}}: {{W-|rif|aberkan|n}} * {{Z|tsg}}: {{W-|tsg|maitum}} * {{Z|th}}: {{W+|th|ดำ}} * {{Z|te}}: {{W+|te|నల్ల}}, {{W+|te|నల్లని}} * {{Z|tt}}: {{W+|tt|кара}} * {{Z|tr}}: {{W+|tr|kara}}, {{W+|tr|siyah}} * {{Z|tk}}: {{W-|tk|gara}} * {{Z|bo}}: {{W-|bo|ནག་པོ}}, {{W-|bo|ནག་ཅན}}, {{W-|bo|རོག་རོག}} * {{Z|to}}: {{W-|to|ʻuliʻuli}} * {{Z|txb}}: {{W-|txb|erkent}} * {{Z|udm}}: {{W-|udm|сьӧд}} * {{Z|ur}}: {{W-|ur|کالا|n|tr=kālā}}, {{W-|ur|سیاہ}} * {{Z|uk}}: {{W+|uk|чо́рний}} * {{Z|vi}}: {{W+|vi|đen}}, {{W+|vi|đen thui}} * {{Z|vo}}: {{W+|vo|blägik}} * {{Z|wa}}: {{W+|wa|noer}} * {{Z|cy}}: {{W+|cy|du}} * {{Z|win}}: {{W-|win|seep}} * {{Z|wo}}: {{W-|wo|kawe-yolet}} * {{Z|kjh}}: {{W-|kjh|хара}} * {{Z|km}}: {{W+|km|ខ្មៅ|tr=kmav}} * {{Z|yai}}: {{W-|yai|шов}} * {{Z|sah}}: {{W-|sah|хара}} * {{Z|yi}}: {{W-|yi|שוואַרץ}} * {{Z|el}}: {{W+|el|μαύρος|n}} *: Kevn: {{W-|grc|μέλας}} * {{Z|zea}}: {{W-|zea|zwart}} * {{Z|za}}: {{W-|za|ndaem}}, {{W-|za|fonx}} * {{Z|zu}}: {{W+|zu|-[[mnyama]]}}{{werger-bin}} === Navdêr === {{ku-tewîn-nav|reş|nêr}} {{navdêr|ku|z=n}} # [[reng|Reng]]ê reş. #* {{jêder|ku|jêgirtin=Wekû muddeyê hiznê (dema xemgîniyê) temam bûyî axayêd wan û yaxo xizmekî wan ji boy her yekî ehlê meyyitî, anegore halê xwe tiştekî tîne û '''reşêd''' wan heldigire, ji şînê biderdikevin. Lakin eger ew meyyit begzade û yaxo axa û mirovekî kifş bûya elbette paşî panzdeh rojan hakimê wî welatî xelatek hazir dikirîn û dişande pê warisê meyyitî (xwediyê kesê ku miriye) û tînane hizûra xwe û digotêne: Emrê xwedê ye, bilanî tu xweş bî, mirin rêya me hemûyan e. Ew xelat li wî warisî dikirîn û ji '''reşê''' biderdanîn (derdixistin).|{{jêgirtin/Mele Mehmûdê Bayezîdî/Adat û Rusûmatnameê Ekradiye|r=53}}}} ==== Werger ==== {{werger-ser}} * {{Z|fr}}: {{W+|fr|noir|n}} {{werger-bin}} == {{ziman|ckb}} == === Rengdêr === {{rengdêr|ckb|sc=Latn}} # {{ckb-Arab|ڕەش}} pb7jisvdu5o8wtpwsch5ithkn6akx89 6241661 6241660 2026-07-11T20:24:31Z Wikihez 7344 6241661 wikitext text/x-wiki {{bnr-h|res}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{deng|ku|LL-Q36163 (kmr)-Key Mîrza-reş.wav|Deng|Wan}} * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|reş}} [[Wêne:Solid black.svg|thumb|150px|Rengê reş.]] {{rengdêr|ku}} # {{f|ku|reng}} [[reng|Reng]]ê ji hemiyan [[tarî]]tir, [[wek]] rengê [[rejî|rejiyê]]. #: {{panela rengê|000000}} #* {{jêder|ku|jêgirtin=-Tu jî mîna Fêdkayê min esmer î, çevreş, porê te '''reş'''.|{{Jêgirtin/Frîda Hecî Cewarî/Bîranînên Min}}}} #* {{jêder|ku|jêgirtin=Digel ku emrê wî hê sî û pênc bû jî tayekî '''reş''' di porê wî de nemabû.|{{Jêgirtin/Firat Cewerî/Kevoka Spî/1996}}}} #* {{jêder|ku|jêgirtin=Û ew libasêd '''reş''' heta şeş mehan û yaxo salekê li ser ehlê (xizmê) meyyitî dimînin. Ew ehlê meyyitî heta ji şînê bidernekevin naçine dawet û kêfxweşiyan.|{{jêgirtin/Mele Mehmûdê Bayezîdî/Adat û Rusûmatnameê Ekradiye|r=53}}}} # Ji [[ronahî|ronahiyê]] [[bêpar]]. #: {{hevmane|ku|tarî}} #* {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Saqî ko dêm mehweş bitin<br />Kagul ji şêva '''reş''' bitin<br />Qerqef bila ateş bitin}} #* {{jêder|ku|jêgirtin=(...) mîna tîrekê navdilê Qaçax hingavtin, ling lê lerizîn, ber çavên wî '''reş''' bû (...)|{{Jêgirtin/Sîma Semend/Xezal/1996}}}} # [[temirandî]] #: {{nm|ku|Ka wê çirayê '''reş''' bike.}} # [[mirov|Mirov]]ên [[çerm]]reş yên mîna [[Afrîkî|afrîkiyan]]. #: {{hevmane|ku|çermreş}} #* {{jêder|ku|jêgirtin=Zelamekê req û hişk û '''reş''' hate bi nik wan ve.|{{Jêgirtin/Xelîl Duhokî/Antolojiya Çîroka Nû ya Kurmancên Başûr}}}} # [[bêyom]], [[pirr]] [[xirab]], [[nebaş]] #* {{jêder|ku|jêgirtin=Bextê me '''reş''' e, kezeb birîn e.|{{Jêgirtin/Mehmed Uzun/Siya Evînê/1989}}}} ==== Bi alfabeyên din ==== * {{ku-ar|ڕەش}} * {{ku-kr|рәш}} ==== Herwiha ==== * {{hw|ku|riş||Reşwî}} ==== Hevmane ==== * {{g|ku|siyah}} {{i|tenê [[edebî]]}} * {{g|ku|qere-}} {{i|tenê wek [[pêşgir]]}} ==== Jê ==== {{kol3|ku|cure=Jê |reş bûn<q:lêker> |reş kirin<q:lêker> |reşbûn<q:navdêr> |reşkirin<q:navdêr> |reşbûyî<q:rengdêr> |reşkirî<q:rengdêr> |reşokî |reşole |reşnivîs |reşmeh |reşname |reşpatî |ripîreş }} ==== Etîmolojî ==== Taliyê ji {{ji|ira-pro|ku|*ra(n)ǰ-|w=reng kirin, boyax kirin}}. Hevreha {{hv|ckb|ڕەش}}, {{hv|kho|rraşa|w=ya ku bi rengê tarî}}, {{hv|tly|رش|tr=rəş|w=qehweyiya zelal}}, {{hv|sog|tr=rɣš-|ts=raxš|w={{w|Rexş}}, hespê [[Ristem]]}}, {{hv|fa|رخش|tr=rexş|w=sor}}, {{hv|mzn|رش|tr=raš|w=sor}}. Guherîna maneya rengan di zimanên hindûewropî de diyardeyeke berbelav e. ;{{biçûk|Çavkanî: * {{Cheung|r=314}} }} ==== Binêre herwiha ==== {{tablo:reng/ku}} ==== Bide ber ==== * {{g|ku|reştarî}} * {{g|ku|reşûşîn kirin}} * {{g|ku|reşûşîn}} * {{g|ku|reşpoş}} ==== Bi zaravayên din ==== * {{Z|ckb}}: {{W-|ckb|ڕەش|tr=reş}} * {{Z|sdh}}: {{W-|sdh|siya|sc=Latn}}, {{W-|sdh|siyaw|sc=Latn}} * {{Z|hac}}: {{W-|hac|siyaw|sc=Latn}} * {{Z|zza}}: {{W-|zza|sîya}} ==== Werger ==== {{werger-ser}} * {{Z|ab}}: {{W-|ab|аиқәаҵәа}} * {{Z|ace}}: {{W-|ace|itam}} * {{Z|adt}}: {{W-|adt|waurrunha}} * {{Z|af}}: {{W+|af|swart}} * {{Z|akl}}: {{W-|akl|maitum}} * {{Z|sq}}: {{W+|sq|zi}} * {{Z|de}}: {{W+|de|schwarz}} * {{Z|alt}}: {{W-|alt|кара}} * {{Z|am}}: {{W-|am|ጥቁር}} * {{Z|ani}}: {{W-|ani|бечӏедир}} * {{Z|rme}}: {{W-|rme|kalo}} * Apaçî: *: {{Z|apw}}: {{W-|apw|diłhił}} * {{Z|an}}: {{W-|an|negro}} * {{Z|rup}}: {{W-|rup|negru}}, {{W+|rup|laiu}} * {{Z|aer}}: {{W-|aer|artepe}} * {{Z|as}}: {{W-|as|ক‌’লা}}, {{W-|as|কুলা}} * {{Z|ast}}: {{W+|ast|ñegru}}, {{W+|ast|negru}}, {{W+|ast|prietu}} * {{Z|cni}}: {{W-|cni|cheenkari}}, {{W-|cni|kisaari}} * {{Z|atj}}: {{W-|atj|makatewaw}} * {{Z|aot}}: {{W-|aot|pinak}} * {{Z|av}}: {{W-|av|чӏегӏера}}, {{W-|av|чӏегӏераб}} * {{Z|ay}}: {{W-|ay|ch’iyara}} * {{Z|az}}: {{W+|az|qara}} * {{Z|ban}}: {{W-|ban|badeng}} * {{Z|bjn}}: {{W-|bjn|hirang}} * {{Z|eu}}: {{W-|eu|beltz}} * {{Z|ba}}: {{W-|ba|ҡара}} * {{Z|bbl}}: {{W-|bbl|ჺარჭინ}} * {{Z|be}}: {{W+|be|чо́рны}} * {{Z|bn}}: {{W+|bn|কালো}}, {{W+|bn|কাল}} * {{Z|br}}: {{W+|br|du}} * {{Z|bug}}: {{W-|bug|ma-lotoŋ}} * {{Z|mbb}}: {{W-|mbb|me'item}} * {{Z|bg}}: {{W+|bg|че́рен}} * {{Z|my}}: {{W+|my|နက်}}, {{W+|my|မည်း}} * {{Z|bua}}: {{W-|bua|хара}} * {{Z|kac}}: {{W-|kac|chyang}} * {{Z|dz}}: {{W-|dz|གནགཔོ}} * {{Z|ccc}}: {{W-|ccc|kosewa}} * {{Z|ce}}: {{W-|ce|ӏаьржа}} * {{Z|cs}}: {{W+|cs|černý}} * {{Z|chr}}: {{W-|chr|ᎬᎿᎨ}} * {{Z|cic}}: {{W-|cic|losa'}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|黑|tr=hak1}}, {{W-|yue|黑色|tr=haak1 sik1, hak1 sik1}} *: {{Z|dng}}: {{W-|dng|хи}} *: {{Z|cmn}}: {{W+|cmn|黑|tr=hēi}}, {{W+|cmn|黑色|tr=hēisè}}, {{W+|cmn|烏色|tr=wūsè}} *: {{Z|cdo}}: {{W-|cdo|烏|tr=ŭ}} *: {{Z|nan}}: {{W-|nan|黑|tr=hek}}, {{W-|nan|黑色|tr=hek-sek}}, {{W+|nan|烏色|tr=o͘-siak / o͘-sek}} *: {{Z|wuu}}: {{W-|wuu|黑}} * {{Z|cv}}: {{W-|cv|хура}} * {{Z|chk}}: {{W-|chk|chon}} * {{Z|dlm}}: {{W-|dlm|fosc}} * {{Z|da}}: {{W+|da|sort}} * {{Z|dgr}}: {{W-|dgr|dezǫ}} * {{Z|dlg}}: {{W-|dlg|кара}} * {{Z|ovd}}: {{W-|ovd|swart}} * {{Z|id}}: {{W+|id|hitam}} * {{Z|ar}}: {{W+|ar|أَسْوَد|n}}, {{W-|ar|سَوْدَاء|m}}, {{W-|ar|سُود|p}} *: {{Z|arz}}: {{W-|arz|اسود|tr=eswid}} *: {{Z|acw}}: {{W-|acw|أسود|tr=ʾaswad}} *: {{Z|ary}}: {{W-|ary|كحل|tr=kḥal}}, {{W-|ary|سود|tr=swad}} * {{Z|hy}}: {{W-|hy|սև}} * {{Z|myv}}: {{W-|myv|раужо}} * {{Z|eo}}: {{W+|eo|nigra}} * {{Z|et}}: {{W+|et|must}} * {{Z|ett}}: {{W-|ett|𐌑𐌖𐌓𐌉}} * {{Z|eve}}: {{W-|eve|хакарин}} * {{Z|evn}}: {{W-|evn|конңорин}} * {{Z|ee}}: {{W-|ee|yibɔ}} * {{Z|ext}}: {{W-|ext|negru}} * {{Z|fa}}: {{W+|fa|سیاه|tr=siyâh}} * {{Z|fo}}: {{W+|fo|svartur}} * {{Z|fj}}: {{W+|fj|loaloa}} * {{Z|fi}}: {{W+|fi|musta}} * {{Z|fr}}: {{W+|fr|noir}} * {{Z|fur}}: {{W-|fur|neri}} * {{Z|frr}}: *: Föhr: {{W-|frr|suart}} *: Hallig: {{W-|frr|süürt}} *: {{Z|frr}}: {{W-|frr|suurt}} * {{Z|fy}}: {{W+|fy|swart}} * {{Z|gd}}: {{W+|gd|dubh}} * {{Z|gl}}: {{W+|gl|negro}} * {{Z|gdo}}: {{W-|gdo|бечӏер}} * {{Z|gon}}: {{W-|gon|నల్లా|tr=nallā}} * {{Z|gor}}: {{W-|gor|yitomo}} * {{Z|got}}: {{W-|got|𐍃𐍅𐌰𐍂𐍄𐍃}} * {{Z|gu}}: {{W+|gu|કાળું}} * {{Z|ka}}: {{W+|ka|შავი}} * {{Z|ht}}: {{W-|ht|nwa}} * {{Z|hur}}: {{W-|hur|ts'q'éyx̱}} *: {{Z|hur}}: {{W-|hur|tsq'ix}} * {{Z|haw}}: {{W-|haw|ʻeleʻele}} * {{Z|mba}}: {{W-|mba|maitum}} * {{Z|hi}}: {{W+|hi|काला}}, {{W+|hi|कारौ}} * {{Z|hil}}: {{W-|hil|maitum}} * {{Z|mww}}: {{W-|mww|dub}} * {{Z|nl}}: {{W+|nl|zwart}} * {{Z|hop}}: {{W-|hop|qömvi}} * {{Z|ibg}}: {{W-|ibg|ngisit}} * {{Z|he}}: {{W+|he|שחור|tr=shakhór|cuda=שחור \ שָׁחֹר}}, {{W-|he|שחורה|m|tr=sh'khorá|cuda=שחורה \ שְׁחֹרָה}} * {{Z|io}}: {{W+|io|nigra}} * {{Z|ig}}: {{W-|ig|nwa}} * {{Z|ilo}}: {{W-|ilo|nangisit}} * {{Z|ang}}: {{W-|ang|blæc}}, {{W-|ang|sweart}} * {{Z|en}}: {{W+|en|black}} * {{Z|inh}}: {{W-|inh|ӏаьржа}} * {{Z|ia}}: {{W+|ia|nigre}} * {{Z|ill}}: {{W-|ill|maitem}} * {{Z|ga}}: {{W+|ga|dubh}} * {{Z|isd}}: {{W-|isd|ngisit}} * {{Z|ist}}: {{W-|ist|nìgaro}}, {{W-|ist|nìgro}} * {{Z|it}}: {{W+|it|nero}} * {{Z|ium}}: {{W-|ium|jieqv}} * {{Z|is}}: {{W+|is|svartur}} * {{Z|ja}}: {{W+|ja|黒い|tr=くろい, kuroi}}, {{W-|ja|[[黒色]]の|tr=こくしょくの, kokushoku no}} * {{Z|jv}}: {{W+|jv|ireng}}, {{W-|jv|ireŋ}}, {{W-|jv|cemeŋ}}, {{W-|jv|hirěng}} * {{Z|kl}}: {{W+|kl|qernertoq}} * {{Z|xal}}: {{W-|xal|хар}} * {{Z|kn}}: {{W+|kn|ಕಪ್ಪು}} * {{Z|pam}}: {{W-|pam|matuling}} * {{Z|krc}}: {{W-|krc|къара|tr=qara}} * {{Z|csb}}: {{W-|csb|czôrny}} * {{Z|ca}}: {{W+|ca|negre}} * {{Z|zku}}: {{W-|zku|pulyuna}} * {{Z|qu}}: {{W-|qu|yana}} * {{Z|kjj}}: {{W-|kjj|мичӏаь}} * {{Z|ky}}: {{W+|ky|кара}}, {{W-|ky|күңүрт кара}}, {{W+|ky|караңгы}}, {{W+|ky|каралоо}}, {{W+|ky|ушактоо}}, {{W+|ky|жамандоо}}, {{W+|ky|жаманатты кылуу}}, {{W+|ky|жала жабуу}}, {{W+|ky|көө}} * {{Z|kg}}: {{W-|kg|ndombe}} * {{Z|ki}}: {{W-|ki|-irũ}} * {{Z|si}}: {{W+|si|කළු}} * {{Z|koi}}: {{W-|koi|сьӧд}} * {{Z|ko}}: {{W+|ko|검다}}, {{W+|ko|검은}}, {{W+|ko|까맣다}}, {{W-|ko|까만}} * {{Z|kw}}: {{W-|kw|du}} * {{Z|co}}: {{W+|co|neru}} * {{Z|mfe}}: {{W-|mfe|nwar}} * {{Z|kum}}: {{W-|kum|къара|tr=qara}} * {{Z|qui}}: {{W-|qui|shĺpa}} * {{Z|lbj}}: {{W-|lbj|ནག་པོ}} * {{Z|lld}}: {{W-|lld|fosch|n}} * {{Z|lad}}: {{W-|lad|preto}} * {{Z|lkt}}: {{W-|lkt|sápa}} * {{Z|ltg}}: {{W-|ltg|malns}} * {{Z|la}}: {{W+|la|ater}}, {{W+|la|niger}} * {{Z|lv}}: {{W+|lv|melns}} * {{Z|lo}}: {{W-|lo|ດຳ}} * {{Z|lez}}: {{W-|lez|чӏулав}} * {{Z|mhx}}: {{W-|mhx|no, |tr=nòʔ}} * {{Z|ln}}: {{W-|ln|moíndo}} * {{Z|lij}}: {{W-|lij|néigro}} * {{Z|li}}: {{W+|li|zwart}} * {{Z|lt}}: {{W-|lt|júodas}} * {{Z|lmo}}: {{W-|lmo|négher}}, {{W-|lmo|negro}} * {{Z|khb}}: {{W-|khb|ᦡᧄ}} * {{Z|mhn}}: {{W-|mhn|schbòrz}} * {{Z|mad}}: {{W-|mad|celleng}} * {{Z|mak}}: {{W-|mak|le'leng}} * {{Z|mk}}: {{W-|mk|црн}} * {{Z|mg}}: {{W+|mg|mainty}} * {{Z|ml}}: {{W+|ml|കറുപ്പ്}} * {{Z|ms}}: {{W+|ms|hitam}}, {{W+|ms|aswad}}, {{W-|ms|lotong}}, {{W-|ms|lutung}}, {{W-|ms|lutong}} *: {{Z|ms}}: {{W-|ms|هيتم}}, {{W-|ms|اسود}}, {{W-|ms|لوتوڠ}} * {{Z|mt}}: {{W+|mt|iswed|n}}, {{W-|mt|sewda|m}}, {{W-|mt|suwed|p}} * {{Z|mnc}}: {{W-|mnc|ᠰᠠᡥᠠᠯᡳᠶᠠᠨ}}, {{W-|mnc|ᡴᠠᡵᠠ|tr=kara}} * {{Z|gv}}: {{W-|gv|doo}} * {{Z|msk}}: {{W-|msk|maitum}} * {{Z|mi}}: {{W+|mi|mangu}} * {{Z|mrw}}: {{W-|mrw|maitem}}, {{W-|mrw|delem}} * {{Z|mr}}: {{W+|mr|काळा|n}} * {{Z|mrc}}: {{W-|mrc|nilyig}} * {{Z|mop}}: {{W-|mop|bʼox}} * {{Z|hu}}: {{W+|hu|fekete}} * {{Z|egy}}: {{W-egy|km|h=km-m-D3}} * {{Z|lus}}: {{W-|lus|dum}} * {{Z|min}}: {{W-|min|itam}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|хар}} *: Mongolî: {{W-|mn|ᠬᠠᠷ᠎ᠠ}} * {{Z|nfr}}: {{W-|nfr|wɔɔ}} * Nahuatl: *: {{Z|nhn}}: {{W-|nhn|tliltic}} *: Klasîk: {{W-|nci|tliltic}}, {{W-|nci|capotztic}} * {{Z|naq}}: {{W-|naq|ǂnū}} * {{Z|nmb}}: {{W-|nmb|im'ət}} * {{Z|gld}}: {{W-|gld|сахарин}} * {{Z|nap}}: {{W-|nap|niro}} * {{Z|nv}}: {{W-|nv|łizhin}} * {{Z|na}}: {{W+|na|etangang}}, {{W-|na|etañañ}}, {{W-|na|etaŋaŋ}} * {{Z|nxq}}: {{W-|nxq|naq}} * {{Z|nds}}: *: {{Z|nds-de}}: {{W-|nds-de|swart}} * {{Z|ne}}: {{W+|ne|कालो}} * {{Z|nay}}: {{W-|nay|kro:tin}} * {{Z|nia}}: {{W-|nia|a-itö}} * {{Z|nog}}: {{W-|nog|кара}} * {{Z|nuk}}: {{W-|nuk|tupkuk}} * {{Z|nrf}}: {{W-|nrf|nièr|n}}, {{W-|nrf|né|n}}, {{W-|nrf|néthe|m}}, {{W-|nrf|naithe|m}} * {{Z|non}}: {{W-|non|svartr}}, {{W-|non|blakkr}} * {{Z|no}}: {{W+|no|svart}}, {{W+|no|sort}} * {{Z|nwy}}: {{W-|nwy|gahuntee}} * {{Z|ood}}: {{W-|ood|chuk}} * {{Z|oj}}: {{W-|oj|makade-}}, {{W-|oj|makadewaa}}, {{W-|oj|makadewizi}} * {{Z|oc}}: {{W+|oc|negre}} * {{Z|or}}: {{W+|or|କଲା}} * {{Z|om}}: {{W+|om|gurraacha}} * {{Z|os}}: {{W-|os|сау}} * {{Z|ug}}: {{W+|ug|قارا}} * {{Z|uz}}: {{W+|uz|qora}}, {{W+|uz|siyoh}} * {{Z|pag}}: {{W-|pag|deket}} * {{Z|ps}}: {{W+|ps|تور}} * {{Z|pms}}: {{W-|pms|neir}} * {{Z|pjt}}: {{W-|pjt|maṟu}} * {{Z|pl}}: {{W+|pl|czarny}} * {{Z|pt}}: {{W+|pt|preto}}, {{W+|pt|atro}}, {{W+|pt|negro}} * {{Z|pa}}: {{W+|pa|ਕਾਲਾ}} * {{Z|kk}}: {{W+|kk|қара}} * {{Z|cop}}: {{W-|cop|ⲭⲁⲙⲉ}} * {{Z|rap}}: {{W-|rap|kere kere}}, {{W-|rap|uri uri}} * {{Z|rhg}}: {{W-|rhg|hala}} * {{Z|rgn}}: {{W-|rgn|négar}} * {{Z|rm}}: {{W-|rm|nair}} * {{Z|rom}}: {{W-|rom|kalo}} *: {{Z|rmn}}: {{W-|rmn|kalo}} *: {{Z|rml}}: {{W-|rml|kalo}} *: {{Z|rmc}}: {{W-|rmc|kalo}} *: {{Z|rmo}}: {{W-|rmo|kalo}} *: {{Z|rmy}}: {{W-|rmy|kalo}} * {{Z|ro}}: {{W+|ro|negru}} * {{Z|ru}}: {{W+|ru|чёрный}}, {{W+|ru|вороно́й}} * {{Z|str}}: {{W-|str|NEKIX}} * {{Z|se}}: {{W-|se|čáhppes}} * {{Z|sa}}: {{W+|sa|कृष्ण}}, {{W+|sa|काला}} * Sardinian: *: {{Z|sc}}: {{W-|sc|nieddu|n}} *: {{Z|sc}}: {{W-|sc|niéddhu|n}} *: {{Z|sc}}: {{W-|sc|nigheddu|n}} * {{Z|sas}}: {{W-|sas|bidəŋ}} * {{Z|ceb}}: {{W-|ceb|itom}} * {{Z|scn}}: {{W+|scn|nìuru}} * {{Z|sd}}: {{W+|sd|ڪارو}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|цр̑н}} *: Latînî: {{W+|sh|cȓn}} * {{Z|syl}}: {{W-|syl|ꠇꠣꠟꠣ}} * {{Z|cu}}: {{W-|cu|чрьнъ}} * {{Z|sk}}: {{W-|sk|čierny}} * {{Z|sl}}: {{W+|sl|črn}} * {{Z|zlw-slv}}: {{W-|zlw-slv|čǻrnï}} * {{Z|so}}: {{W+|so|madow}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|carny}} *: {{Z|hsb}}: {{W+|hsb|čorny}} * {{Z|es}}: {{W+|es|negro}} * {{Z|su}}: {{W-|su|hideung}} * {{Z|sva}}: {{W-|sva|მეშხე}} * {{Z|sw}}: {{W-|sw|eusi}} * {{Z|ss}}: {{W-|ss|mnyáma}} * {{Z|sv}}: {{W+|sv|svart}} * {{Z|shy}}: {{W-|shy|aberkan}} * {{Z|xsr}}: {{W-|xsr|ནག་པུ|tr=nakpu}} * {{Z|zdj}}: {{W-|zdj|-[[ɗu]]}} * {{Z|sn}}: {{W-|sn|dema}} * {{Z|cjs}}: {{W-|cjs|қара|tr=qara}} * {{Z|tab}}: {{W-|tab|кӏару}} * {{Z|tg}}: {{W+|tg|сиёҳ}} * {{Z|tl}}: {{W+|tl|itim}} * {{Z|ty}}: {{W-|ty|ʻereʻere}} * {{Z|ta}}: {{W+|ta|கருப்பு}} * {{Z|roa-tar}}: {{W-|roa-tar|gnure}} * {{Z|rif}}: {{W-|rif|aberkan|n}} * {{Z|tsg}}: {{W-|tsg|maitum}} * {{Z|th}}: {{W+|th|ดำ}} * {{Z|te}}: {{W+|te|నల్ల}}, {{W+|te|నల్లని}} * {{Z|tt}}: {{W+|tt|кара}} * {{Z|tr}}: {{W+|tr|kara}}, {{W+|tr|siyah}} * {{Z|tk}}: {{W-|tk|gara}} * {{Z|bo}}: {{W-|bo|ནག་པོ}}, {{W-|bo|ནག་ཅན}}, {{W-|bo|རོག་རོག}} * {{Z|to}}: {{W-|to|ʻuliʻuli}} * {{Z|txb}}: {{W-|txb|erkent}} * {{Z|udm}}: {{W-|udm|сьӧд}} * {{Z|ur}}: {{W-|ur|کالا|n|tr=kālā}}, {{W-|ur|سیاہ}} * {{Z|uk}}: {{W+|uk|чо́рний}} * {{Z|vi}}: {{W+|vi|đen}}, {{W+|vi|đen thui}} * {{Z|vo}}: {{W+|vo|blägik}} * {{Z|wa}}: {{W+|wa|noer}} * {{Z|cy}}: {{W+|cy|du}} * {{Z|win}}: {{W-|win|seep}} * {{Z|wo}}: {{W-|wo|kawe-yolet}} * {{Z|kjh}}: {{W-|kjh|хара}} * {{Z|km}}: {{W+|km|ខ្មៅ|tr=kmav}} * {{Z|yai}}: {{W-|yai|шов}} * {{Z|sah}}: {{W-|sah|хара}} * {{Z|yi}}: {{W-|yi|שוואַרץ}} * {{Z|el}}: {{W+|el|μαύρος|n}} *: Kevn: {{W-|grc|μέλας}} * {{Z|zea}}: {{W-|zea|zwart}} * {{Z|za}}: {{W-|za|ndaem}}, {{W-|za|fonx}} * {{Z|zu}}: {{W+|zu|-[[mnyama]]}}{{werger-bin}} === Navdêr === {{ku-tewîn-nav|reş|nêr}} {{navdêr|ku|z=n}} # [[reng|Reng]]ê reş. #* {{jêder|ku|jêgirtin=Wekû muddeyê hiznê (dema xemgîniyê) temam bûyî axayêd wan û yaxo xizmekî wan ji boy her yekî ehlê meyyitî, anegore halê xwe tiştekî tîne û '''reşêd''' wan heldigire, ji şînê biderdikevin. Lakin eger ew meyyit begzade û yaxo axa û mirovekî kifş bûya elbette paşî panzdeh rojan hakimê wî welatî xelatek hazir dikirîn û dişande pê warisê meyyitî (xwediyê kesê ku miriye) û tînane hizûra xwe û digotêne: Emrê xwedê ye, bilanî tu xweş bî, mirin rêya me hemûyan e. Ew xelat li wî warisî dikirîn û ji '''reşê''' biderdanîn (derdixistin).|{{jêgirtin/Mele Mehmûdê Bayezîdî/Adat û Rusûmatnameê Ekradiye|r=53}}}} ==== Werger ==== {{werger-ser}} * {{Z|fr}}: {{W+|fr|noir|n}} {{werger-bin}} == {{ziman|ckb}} == === Rengdêr === {{rengdêr|ckb|sc=Latn}} # {{ckb-Arab|ڕەش}} d336mtiiix970cfh909eviim1v8kdwu pel 0 3393 6241662 6103593 2026-07-11T20:30:05Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241662 wikitext text/x-wiki {{binêre herwiha/pel}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA|pʰɛl}} * {{ku-kîte}} === Navdêr 1 === {{ku-tewîn-nav|pel|nêr}} [[Wêne:Leaf 1 web.jpg|thumb|pel (1)]] {{navdêr|ku|z=n}}, {{p-ya req}} # {{maneid|ku|riwek}} [[parçe|Parçe]]yên [[çeq]]ên [[dar]]an ve [[şên]] dibin. ([[pêşî]] ji [[bişkoj]]an [[pişkivîn|dipişkivin]], [[paşî]] [[kesk]] dibin û [[talî|taliyê]] [[beyîn|dibeyin]] anku [[zer]] dibin û [[werîn|diwerin]] anku [[weşîn|diweşin]]) #: {{hevmane|ku|belçim|belçîm|bilçik|belçûm|pelçim|pelçîm|pelçûm}} # [[per]], [[kaxez]], [[weraqe]], [[belgename]] ==== Bi alfabeyên din ==== * {{ku-ar|پەل}} ==== Ji wêjeya klasîk ==== * {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Ah-i bêgavê ji dil tên me ji pêta di ceger</br>Bes tu bêfeyde nesîhet ke me dil bûye '''pelek'''}} ==== Herwiha ==== {{kol3|ku|cure=Herwiha|sernav = [https://twitter.com/wikiferheng/status/1710338730089689440 Çavkanî] | {{hw|ku|pelg||Sirûc|Bîraçik|Xelfetî}} | {{hw|ku|pel||Mêrdîn|Sêwreg|Amed|Pasûr|Çewlîg|Bazîd}} | {{hw|ku|pelçim||Botan}} | {{hw|ku|belg||Dîgor|Agirî|Wan}} | {{hw|ku|belçim||Dêrsim|Serhed}} | {{hw|ku|pelç||Hewag}} | {{hw|ku|per||Semsûr}} }} ==== Bide ber ==== {{stûn| * {{g|ku|pell}} * {{g|ku|pal}} * {{g|ku|pêl}} * {{g|ku|pil}} * {{g|ku|pîl}} * {{g|ku|pol}} * {{g|ku|pul}} * {{g|ku|pûl}} * {{g|ku|bel}} }} ==== Jê ==== {{kol3|ku|cure=Jê |pel girtin<q:lêker> |pelgirtin<q:navdêr> |pelçûn<q:navdêr> }} ==== Etîmolojî ==== Hevreha şêxbizinî ''[[welg]]'', zazakî ''[[velg]]'' * {{ji|ine-pro|ku|-}}: *'''welə'''- ("hirî, pûrt") > *'''wolko'''- ("mû, hirî, pûrt; giya; daristan") :*{{ji|ira-pro||-}}: *'''warka'''- ("belg, pel") ::{{ae}}: '''verke'''- ("belg, pel") ::{{xpr}}: '''wrgr''' ("belg, pel") ::{{pal}}: '''werg ''' ("belg, pel") ::{{sog}}: '''wrkr ''' ("belg, pel") ::{{fa}}: '''berg''' ("belg, pel") ::{{mzn}}: '''verek''' ("belg, pel") ::{{ku}}: '''belg > pelg > pel''' ::{{zza}}: '''[[velg]]''' ("belg, pel") :{{sa}}: '''velke'''- ("[[per]], [[bask]]") ... :{{la}}: '''vellus'''- ("hirî, pûrt") :{{de}}: '''Wolle'''- ("hirî, pûrt") :{{en}}: '''wool'''- ("hirî, pûrt") ;{{biçûk|Çavkanî: * {{Horn|r=47}} * {{Lubotsky|r=98}} * {{Pokorny|r=1139}} }} ==== Bi zaravayên din ==== * soranî/erdelanî: gella, pelk * zazakî/kirmanckî: pel, pelçim, pure, velg, * kelhûrî/feylî/şêxbizinî: welg, welneg, werg, belg, berg, pelg * hewramî/şebekî: welg ==== Werger ==== {{werger-ser|riwek|id=riwek}} * {{Z|ab}}: {{W-|ab|абӷьы}} * {{Z|ace}}: {{W-|ace|ôn}} * {{Z|ady}}: {{W-|ady|тхьэпкӏэ}} * {{Z|aa}}: {{W-|aa|dalaa}} * {{Z|af}}: {{W+|af|blaar}} * {{Z|akl}}: {{W-|akl|dahon}} * {{Z|sq}}: {{W+|sq|gjethe|m-p}} * {{Z|pdc}}: {{W-|pdc|Blatt|nt}} * {{Z|de}}: {{W+|de|Blatt|nt}}, {{W+|de|Laubblatt|nt}} *: {{Z|gsw}}: {{W-|gsw|Blatt|nt}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Blatt|nt}} * {{Z|ryn}}: {{W-|ryn|葉|tr=はー, hā}} * {{Z|ams}}: {{W-|ams|葉|tr=はー, hā}} * {{Z|am}}: {{W-|am|ቅጠል}} * {{Z|an}}: {{W+|an|fuella|m}} * {{Z|arc}}: *: {{Z|syc}}: {{W-|syc|ܛܪܦܐ|n|tr=ṭarpā}} * {{Z|agj}}: {{W-|agj|ቅጠል|tr=qəțäl}} * {{Z|rup}}: {{W-|rup|frãndzã|m}}, {{W-|rup|frundzã|m}} * {{Z|as}}: {{W-|as|পাত|nt}} * {{Z|bno}}: {{W-|bno|rahon}}, {{W-|bno|dahon}} * {{Z|ast}}: {{W+|ast|fueya|m}} * {{Z|ask}}: {{W-|ask|pār}} * {{Z|tay}}: {{W-|tay|abau}} * {{Z|ay}}: {{W+|ay|laphi}} * {{Z|ain}}: {{W-|ain|ハㇺ|tr=ham}} * {{Z|az}}: {{W+|az|yarpaq}} * {{Z|bdq}}: {{W-|bdq|hla}} * {{Z|ban}}: {{W-|ban|don}} * {{Z|eu}}: {{W+|eu|hosto}}, {{W+|eu|orri}} * {{Z|ba}}: {{W-|ba|япраҡ}} * {{Z|be}}: {{W-|be|ліст|n}} * {{Z|bn}}: {{W+|bn|পাতা}} * {{Z|bho}}: {{W-|bho|पान}} * {{Z|bol}}: {{W-|bol|kumi rewe}} * {{Z|br}}: {{W+|br|delienn|m}} * {{Z|kxd}}: {{W-|kxd|daun}} * {{Z|bug}}: {{W-|bug|daung}} * {{Z|bg}}: {{W+|bg|лист|n}}, {{W+|bg|листо́|nt}} * {{Z|my}}: {{W+|my|အရွက်}} * {{Z|bua}}: {{W-|bua|набша}}, {{W-|bua|набшаһан}}, {{W-|bua|намаа}} * {{Z|kac}}: {{W-|kac|lap}} * {{Z|ccc}}: {{W-|ccc|chijpana}} * {{Z|cjm}}: {{W-|cjm|ꨈꨶꨮꩉ}}, {{W-|cjm|ꨨꨤꨩ}} * {{Z|cbk}}: {{W-|cbk|ohas}} * {{Z|ce}}: {{W-|ce|гӏа}} * {{Z|cs}}: {{W+|cs|list|n}} * {{Z|chr}}: {{W-|chr|ᎤᎦᎶᎬ}} * {{Z|ny}}: {{W-|ny|tsamba}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|葉|tr=jip6}}, {{W-|yue|葉子|tr=jip6 zi2}} *: {{Z|dng}}: {{W-|dng|еезы}}, {{W-|dng|еер}}, {{W-|dng|езы}} *: {{Z|hak}}: {{W-|hak|葉|tr=ya̍p}} *: {{Z|cjy}}: {{W-|cjy|葉子|tr=ieh4 zeh}} *: {{Z|cmn}}: {{W+|cmn|葉|tr=yè}}, {{W+|cmn|葉子|tr=yèzi}} *: {{Z|cdo}}: {{W-|cdo|箬箬|tr=niŏh-niŏh}} *: {{Z|nan}}: {{W+|nan|葉|tr=ia̍p}}, {{W+|nan|葉仔|tr=hio̍h-á}} *: {{Z|wuu}}: {{W-|wuu|葉}}, {{W-|wuu|葉子}} *: {{Z|hsn}}: {{W-|hsn|葉子|tr=ie6 zr}} * {{Z|cv}}: {{W-|cv|ҫулҫӑ}} * {{Z|dlm}}: {{W-|dlm|fualja|m}} * {{Z|da}}: {{W+|da|blad|nt}}, {{W-|da|løv|nt}} * {{Z|duu}}: {{W-|duu|vng'lvp}} * {{Z|id}}: {{W+|id|daun}} * {{Z|enq}}: {{W-|enq|yoko}} * {{Z|ar}}: {{W-|ar|وَرَقَة|m}} * {{Z|hy}}: {{W-|hy|տերեւ}} * {{Z|myv}}: {{W-|myv|лопа}} * {{Z|eo}}: {{W+|eo|folio}} * {{Z|et}}: {{W+|et|leht}} * {{Z|gez}}: {{W-|gez|ቈጽል}} * {{Z|eve}}: {{W-|eve|эбдэнрэ}} * {{Z|evn}}: {{W-|evn|авданна}} * {{Z|ee}}: {{W-|ee|aŋgba}} * {{Z|fa}}: {{W+|fa|برگ|tr=barg}} * {{Z|fo}}: {{W-|fo|blað|nt}} * {{Z|fj}}: {{W+|fj|drau}} * {{Z|fi}}: {{W+|fi|lehti}} * {{Z|fon}}: {{W-|fon|ama}} * {{Z|frp}}: {{W-|frp|fôlye|m}} * {{Z|fro}}: {{W-|fro|fueille|m}} * {{Z|fr}}: {{W+|fr|feuille|m}} * {{Z|fur}}: {{W-|fur|fuee|m}} * {{Z|stq}}: {{W-|stq|Blääd|nt}} * {{Z|fy}}: {{W-|fy|blêd}} * {{Z|ff}}: *: Latînî: {{W-|ff|haako}}, {{W-|ff|kaakol}} *: Adlamî: {{W-|ff|𞤸𞤢𞥄𞤳𞤮}}, {{W-|ff|𞤳𞤢𞥄𞤳𞤮𞤤}} * {{Z|fuy}}: {{W-|fuy|hutu}} * {{Z|gd}}: {{W-|gd|duille|m}}, {{W-|gd|duilleag|m}} * {{Z|gl}}: {{W+|gl|folla|m}} * {{Z|glk}}: {{W-|glk|ولگ}} * {{Z|gu}}: {{W-|gu|પાન|m}}, {{W-|gu|પર્ણ|nt}}, {{W-|gu|પાંદડું|nt}}, {{W-|gu|દલ}} * {{Z|ka}}: {{W+|ka|ფოთოლი}} * {{Z|gn}}: {{W+|gn|togue}} * {{Z|gwi}}: {{W-|gwi|chʼatʼan}} * {{Z|ht}}: {{W-|ht|fèy}} * {{Z|haw}}: {{W-|haw|lau}} * {{Z|ha}}: {{W+|ha|ganye}}, {{W-|ha|warƙa}} * {{Z|mba}}: {{W-|mba|dahon}} * {{Z|hi}}: {{W+|hi|पत्ता|n}}, {{W+|hi|पत्ती|m}} * {{Z|ho}}: {{W-|ho|raurau}} * {{Z|hil}}: {{W-|hil|dahon}} * {{Z|meu}}: {{W-|meu|rau}} * {{Z|mww}}: {{W-|mww|nplooj}} * {{Z|nl}}: {{W+|nl|blad|nt}} * {{Z|hop}}: {{W-|hop|nàapi}} * {{Z|he}}: {{W+|he|עָלֶה|n|tr=alé}} * {{Z|io}}: {{W+|io|folio}} * {{Z|ig}}: {{W-|ig|akwụkwọ}} * {{Z|inz}}: {{W-|inz|qap}} * {{Z|ang}}: {{W+|ang|lēaf|nt}} * {{Z|en}}: {{W+|en|leaf}} * {{Z|izh}}: {{W-|izh|lehti}} * {{Z|ia}}: {{W-|ia|folio}} * {{Z|iu}}: {{W-|iu|ᐊᑭᕈᐊᕈᖅ}} * {{Z|ill}}: {{W-|ill|raun}} * {{Z|ga}}: {{W+|ga|duilleog|m}}, {{W+|ga|bileog|m}} * {{Z|it}}: {{W+|it|foglia|m}} * {{Z|ium}}: {{W-|ium|normh}} * {{Z|is}}: {{W+|is|lauf|nt}}, {{W+|is|laufblað|nt}} * {{Z|ja}}: {{W+|ja|葉|tr=は, ha}}, {{W+|ja|葉っぱ|tr=はっぱ, happa}}, {{W+|ja|木の葉|tr=このは, konoha}} * {{Z|jra}}: {{W-|jra|hla}} * {{Z|kaw}}: {{W-|kaw|ron}} * {{Z|jv}}: {{W+|jv|godhong}}, {{W-|jv|ron}} * {{Z|kl}}: {{W-|kl|pilu}} * {{Z|bsh}}: {{W-|bsh|por}} * {{Z|kn}}: {{W+|kn|ಎಲೆ}} * {{Z|pam}}: {{W-|pam|bulung}} * {{Z|krl}}: {{W-|krl|lehti}} * {{Z|csb}}: {{W-|csb|lëst}} * {{Z|ca}}: {{W+|ca|fulla|m}} * {{Z|qu}}: {{W-|qu|raphi}}, {{W-|qu|llaqhi}} * {{Z|kha}}: {{W-|kha|sla}} * {{Z|kzg}}: {{W-|kzg|葉|tr=ぱー, pā}} * {{Z|ky}}: {{W+|ky|жалбырак}} * {{Z|ki}}: {{W-|ki|ithangũ|c5}} * {{Z|si}}: {{W-|si|කොළේ}}, {{W-|si|කොළය}} * {{Z|kyi}}: {{W-|kyi|dun}} * {{Z|koi}}: {{W-|koi|кор}} * {{Z|swb}}: {{W-|swb|wani|c11|c6}} * {{Z|kok}}: {{W-|kok|पाल्लो|tr=pāllo}} * {{Z|ko}}: {{W+|ko|잎}} * {{Z|co}}: {{W+|co|foglia|m}} * {{Z|cr}}: *: {{Z|crk}}: {{W-|crk|nīpiy}} * {{Z|xug}}: {{W-|xug|葉|tr=ぱー, phā}} * {{Z|lad}}: {{W-|lad|foja|m}}, {{W-|lad|yaprak|n}} * {{Z|lkt}}: {{W-|lkt|wahpe}}, {{W-|lkt|ape}} * {{Z|ltg}}: {{W-|ltg|lopa|m}} * {{Z|la}}: {{W+|la|folium|nt}}, {{W-|la|frons|m}} * {{Z|lv}}: {{W+|lv|lapa|m}} * {{Z|lo}}: {{W-|lo|ໃບ}}, {{W+|lo|ໃບໄມ້}} * {{Z|ln}}: {{W-|ln|nkásá|c9|c10}}, {{W-|ln|lokásá|c11|c10}} * {{Z|lij}}: {{W-|lij|féuggia|m}} * {{Z|li}}: {{W+|li|louf|nt}} * {{Z|lt}}: {{W+|lt|lapas|n}} * {{Z|lmo}}: {{W-|lmo|foeuja|m}}, {{W-|lmo|fòia|m}} * {{Z|lg}}: {{W-|lg|ekikoola}} * {{Z|luy}}: {{W-|luy|lisafu}} * {{Z|lb}}: {{W-|lb|Blat|nt}} * {{Z|mhn}}: {{W-|mhn|lap|nt}} * {{Z|mdh}}: {{W-|mdh|laun}} * {{Z|mk}}: {{W-|mk|лист|n}} * {{Z|mg}}: {{W+|mg|ravina}}, {{W+|mg|ravina}} * {{Z|ml}}: {{W+|ml|ഇല}} * {{Z|ms}}: {{W+|ms|daun}} * {{Z|mt}}: {{W-|mt|werqa|m}} * {{Z|mnc}}: {{W-|mnc|ᠠᠪᡩᠠᡥᠠ}} * {{Z|gv}}: {{W-|gv|duillag|m}} * {{Z|mns-nor}}: {{W-|mns-nor|лӯпта}} * {{Z|mi}}: {{W+|mi|rau}}, {{W-|mi|tawhera}} * {{Z|mrw}}: {{W-|mrw|ra'on}} * {{Z|mr}}: {{W-|mr|पर्ण|nt}}, {{W+|mr|पत्र|nt}}, {{W+|mr|दल|nt}} * Marî: *: {{Z|mhr}}: {{W-|mhr|лышташ}} *: {{Z|mrj}}: {{W-|mrj|ӹлӹштӓш}} * {{Z|gun}}: {{W-|gun|ogue}} * {{Z|hu}}: {{W+|hu|levél}}, {{W+|hu|falevél}} * {{Z|mel}}: {{W-|mel|daun}} * {{Z|egy}}: {{W-egy|gꜣbt|h=g-A-b-t-Hn:Z2ss}} * {{Z|mvi}}: {{W-|mvi|葉|tr=ぱー, pā}} * {{Z|lus}}: {{W-|lus|hnah}} * {{Z|min}}: {{W-|min|daun}} * {{Z|mwl}}: {{W-|mwl|fuolha|m}} * {{Z|xpq}}: {{W-|xpq|wunipaq}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|навч}} *: Mongolî: {{W-|mn|ᠨᠠᠪᠴᠢ}} * {{Z|mnw}}: {{W-|mnw|သၠ|tr=hlaˀ}} * {{Z|mtq}}: {{W-|mtq|lả}} * {{Z|nah}}: {{W+|nah|izhuatl}} * {{Z|gld}}: {{W-|gld|хабдата}} * {{Z|nv}}: {{W-|nv|atʼąąʼ}} * {{Z|nds}}: *: {{Z|nds-de}}: {{W-|nds-de|Blatt|nt}} * {{Z|ne}}: {{W+|ne|पात}} * {{Z|ncb}}: {{W-|ncb|dai}} * {{Z|nrf}}: {{W-|nrf|fielle|m}}, {{W-|nrf|fieille|m}}, {{W-|nrf|fuule|m}}, {{W-|nrf|fiëly|m}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|blad|nt}}, {{W+|nb|løv|nt}} *: {{Z|nn}}: {{W-|nn|blad|nt}}, {{W-|nn|lauv|nt}} * {{Z|oj}}: {{W-|oj|aniibiishibag}}, {{W-|oj|aniibiishibagoon|p}}, {{W-|oj|aniibiish}}, {{W-|oj|aniibiishan|p}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᐟ|tr=aniibiishibag}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᑯᐣ|p|tr=aniibiishibagoon}}, {{W-|oj|ᐊᓂᐱᐦᐡ|tr=aniibiish}}, {{W-|oj|ᐊᓂᐱᐦᔕᐣ|p|tr=aniibiishan}} * {{Z|okn}}: {{W-|okn|葉|tr=はー, fā}} * {{Z|ryu}}: {{W-|ryu|葉|tr=ふぁー, fā}} * {{Z|oc}}: {{W+|oc|fuèlha|m}} * {{Z|one}}: {{W-|one|onláhte̲’}} * {{Z|or}}: {{W+|or|ପତ୍ର}} * {{Z|osa}}: {{W-|osa|žąąpé}} * {{Z|os}}: {{W-|os|сыф}} * {{Z|ota}}: {{W-|ota|یپراق|tr=yaprak}} * {{Z|ug}}: {{W-|ug|يوپۇرماق}}, {{W-|ug|ياپراق}} * {{Z|uz}}: {{W+|uz|yaproq}}, {{W+|uz|barg}} * {{Z|pac}}: {{W-|pac|ula}}, {{W-|pac|ila}} * {{Z|pau}}: {{W-|pau|llel}} * Pali: *: {{Z|pi}}: {{W-|pi|ပဏ္ဏ|nt}} *: {{Z|pi}}: {{W-|pi|पण्ण|nt}} *: {{Z|pi}}: {{W-|pi|បណ្ណ|nt}} *: Latînî: {{W-|pi|paṇṇa|nt}} *: {{Z|pi}}: {{W-|pi|පණ්ණ|nt}} *: {{Z|pi}}: {{W-|pi|ปณฺณ|nt}} * {{Z|pap}}: {{W-|pap|foya}} * {{Z|bxd}}: {{W-|bxd|a³¹faʔ⁵⁵}}, {{W-|bxd|sak⁵⁵ faʔ⁵⁵}} * {{Z|ps}}: {{W+|ps|پاڼه|m|tr=pâṇa}} * {{Z|pms}}: {{W-|pms|feuja|m}} * {{Z|ppl}}: {{W-|ppl|iswat}}, {{W-|ppl|izhuat}} * {{Z|pdt}}: {{W-|pdt|Blaut|nt}} * {{Z|pl}}: {{W+|pl|liść|n}} * {{Z|pt}}: {{W+|pt|folha|m}} * {{Z|prn}}: {{W-|prn|pārag}} * {{Z|pa}}: {{W-|pa|ਪੱਤਾ|n}} * {{Z|kk}}: {{W-|kk|жапырақ}} * {{Z|rap}}: {{W-|rap|rua}} * {{Z|rhg}}: {{W-|rhg|fata}} * {{Z|rgn}}: {{W-|rgn|fója|m}} * {{Z|rm}}: {{W-|rm|fegl}} * {{Z|rom}}: {{W-|rom|patrin|m}} * {{Z|ro}}: {{W+|ro|frunză|m}} * {{Z|ru}}: {{W+|ru|лист|n}}, plural for this sense: {{W+|ru|ли́стья|n-p}} * {{Z|ksw}}: {{W-|ksw|သ့ၣ်လၣ်}} * {{Z|ssy}}: {{W-|ssy|dharhaa}} * {{Z|se}}: {{W-|se|lasta}} * {{Z|sm}}: {{W-|sm|lau}} * {{Z|sa}}: {{W+|sa|पर्ण|tr=parṇá|nt}}, {{W+|sa|पत्र|nt}} * {{Z|sc}}: {{W-|sc|fògia|m}} * {{Z|ceb}}: {{W-|ceb|dahon}} * {{Z|sea}}: {{W-|sea|sela}} * {{Z|scn}}: {{W+|scn|fogghia|m}} * {{Z|sd}}: {{W-|sd|پن|n|tr=panu|cuda=پَنُ}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|лист|n}}, {{W-|sh|лиска|m}} *: Latînî: {{W+|sh|list|n}}, {{W+|sh|liska|m}} * {{Z|cu}}: *: Kirîlî: {{W-|cu|листъ|n}} *: Glagolîtîk: {{W-|cu|ⰾⰹⱄⱅⱏ|n}} * {{Z|orv}}: {{W-|orv|листъ|n}} * {{Z|sk}}: {{W+|sk|list|n}} * {{Z|sl}}: {{W+|sl|list|n}} * {{Z|zlw-slv}}: {{W-|zlw-slv|lȧ̃st|n}} * {{Z|so}}: {{W+|so|caleen|m}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|list|n}} *: {{Z|hsb}}: {{W-|hsb|list|n}} * {{Z|es}}: {{W+|es|hoja|m}} * {{Z|su}}: {{W+|su|daun}} * {{Z|sw}}: {{W+|sw|jani|c5|c6}}, {{W+|sw|msahafu|c3|c4}} * {{Z|sv}}: {{W+|sv|blad|nt}}, {{W+|sv|löv|nt}} * {{Z|shn}}: {{W-|shn|မႂ်}}, {{W-|shn|ဝႂ်}} * {{Z|zdj}}: {{W-|zdj|wani|c11|c10}} * {{Z|sn}}: {{W-|sn|shizha}} * {{Z|tg}}: {{W+|tg|барг}} * {{Z|tl}}: {{W+|tl|dahon}} * {{Z|tly}}: {{W-|tly|لیو}} * {{Z|ta}}: {{W+|ta|இலை}} * {{Z|twf}}: {{W-|twf|ə̂na}} * {{Z|roa-tar}}: {{W-|roa-tar|fogghie|m}} * {{Z|rif}}: {{W-|rif|afar|n}}, {{W-|rif|tifrešt|m}} * {{Z|tsg}}: {{W-|tsg|dahun}} * {{Z|th}}: {{W+|th|ใบ}}, {{W+|th|ใบไม้}} * {{Z|te}}: {{W+|te|ఆకు}} * {{Z|tzm}}: {{W-|tzm|ⵉⴼⴻⵔ|n}} * {{Z|tea}}: {{W-|tea|sela}} * {{Z|tt}}: {{W+|tt|яфрак}} * {{Z|tet}}: {{W-|tet|roo}} * {{Z|tr}}: {{W+|tr|yaprak}} * {{Z|tk}}: {{W-|tk|ýaprak}} * {{Z|bo}}: {{W-|bo|ལོ་མ།}} * {{Z|tli}}: {{W-|tli|kayaaní}} * {{Z|tpi}}: {{W-|tpi|lip}} * {{Z|tkn}}: {{W-|tkn|葉|tr=はー, hā}} * {{Z|xto}}: {{W-|xto|pält}} * {{Z|txb}}: {{W-|txb|pilta}} * {{Z|trm}}: {{W-|trm|påṭ}} * {{Z|tcy}}: {{W-|tcy|ಅಡಿಪಿರೆ}} * {{Z|tvl}}: {{W-|tvl|lau}} * {{Z|tpw}}: {{W-|tpw|oba}} * {{Z|udi}}: {{W-|udi|хазал}} * {{Z|udm}}: {{W-|udm|куар}} * {{Z|ur}}: {{W-|ur|پتی|m|tr=patti}} * {{Z|uk}}: {{W+|uk|лист|n}} * {{Z|vec}}: {{W+|vec|foja|m}}, {{W-|vec|fogia|m}} * {{Z|vep}}: {{W-|vep|leht}} * {{Z|vi}}: {{W+|vi|lá}} * {{Z|vo}}: {{W+|vo|bled}} * {{Z|vor}}: {{W-|vor|leht'}} * {{Z|vot}}: {{W-|vot|lehti}} * {{Z|wbk}}: {{W-|wbk|poṭ}} * {{Z|wa}}: {{W+|wa|foye|m}} * {{Z|war}}: {{W-|war|dáhon}} * {{Z|cy}}: {{W+|cy|deilen|m}} * {{Z|wym}}: {{W-|wym|błot|nt}} * {{Z|wo}}: {{W+|wo|xob}} * {{Z|km}}: {{W+|km|ស្លឹក}}, {{W-|km|ស្លឹកឈើ}} * {{Z|xh}}: {{W-|xh|igqabi|c5|c6}} * {{Z|rys}}: {{W-|rys|葉|tr=ぱー, pā}} * {{Z|sah}}: {{W-|sah|сэбирдэх}} * {{Z|yag}}: {{W-|yag|Suka}} * {{Z|yi}}: {{W-|yi|בלאַט|n|m}} * {{Z|yoi}}: {{W-|yoi|葉|tr=はー, hā}} * {{Z|yox}}: {{W-|yox|葉|tr=ぱー, pā}} * {{Z|yo}}: {{W-|yo|ewé}} * {{Z|el}}: {{W+|el|φύλλο|nt}} *: Kevn: {{W-|grc|φύλλον|nt}}, {{W-|grc|πέταλον|nt}} * {{Z|zea}}: {{W-|zea|blad|nt}} * {{Z|za}}: {{W-|za|mbaw}} * {{Z|zu}}: {{W+|zu|ikhasi|c5|c6}}, {{W+|zu|iqabi|c5|c6}} {{werger-bin}} :{{werger çavkanî|en|leaf|beş=Ev qismê Wergerê|oldid=76702326}} {{werger-ser|per, kaxez, weraqe, belgename}} * {{Z|de}}: {{W+|de|Laub}} {{n}}, {{W+|de|Seite}} {{m}}, {{W+|de|Wedel|guman=erê}} {{n}} * {{Z|fa}}: {{W+|fa|برگ}}, {{W+|fa|سند}}, {{W+|fa|صفحه}}, {{W+|fa|برگه|guman=erê}}, {{W-|fa|شراره آتش|guman=erê}}, {{W+|fa|کاغذ|guman=erê}}, {{W+|fa|مدرک|guman=erê}} * {{Z|en}}: {{W+|en|covey}}, {{W+|en|foliage}}, {{W+|en|frond}}, {{W+|en|gleed}}, {{W+|en|platoon}}, {{W+|en|file}}, {{W+|en|phyllo-}} * {{Z|tr}}: {{W+|tr|belge}}, {{W+|tr|çalkantı}}, {{W+|tr|çapak}}, {{W+|tr|lahza|guman=erê}} {{werger-bin}} === Navdêr 2 === [[Wêne:Embers 01.JPG|thumb|250px|pel (2)]] {{navdêr|ku|z=n}} # [[pêt]], <br>[[parçe]]yên [[agir]]î yên ji [[pirt]]ên [[dar]]î yan [[kumir]]ê <br>(yên ku agirî girtine û dişewitin lê hê nebûne [[xwelî]]) ==== Herwiha ==== * {{g|ku|pêlox}} * {{g|ku|pêreng}} * {{g|ku|piring}} * {{g|ku|piloxt}} ==== Bi alfabeyên din ==== * {{ku-ar|په‌ل}} ==== Etîmolojî ==== Herwiha [[piring]], [[pêreng]], ji {{ji|ine-pro|ku|-}} *[[péh₂ur]] ([[agir]]), hevreha çekî [[pýř]] (pel), {{hv|grc|πῦρ}} (pûr: agir > kurdî [[pîroman]]), [[toxarî]] A ''por'' (agir), toxarî B ''puwar'' (agir), hîtîtî ''paḫḫur'' ([[agir]]), danmarkî / norwecî / {{hv|sv|fyr}} (agir), îngilîzî [[fire]] (agir), {{hv|hy|հուր}} (hur: agir)... ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Glut}} {{m}} * {{Z|zh}}: *: [[mandarînî]]: {{W+|cmn|餘燼|sc=Hani|xs=Mandarin}}, {{W+|cmn|余烬|tr=yújìn|sc=Hani|xs=Mandarin}} * {{Z|ar}}: {{W-|ar|جمرة|tr=cemre}} * {{Z|hy}}: {{W-|hy|մարմրող ածուխ|tr=marmroġ açux}} * {{Z|eo}}: {{W-|eo|braĝo|xs=Esperanto}}, {{W-|eo|ardaĵo|xs=Esperanto}} * {{Z|fa}}: {{W+|fa|شعله|sc=fa-Arab}} * {{Z|fi}}: {{W+|fi|kekäle}} * {{Z|fr}}: {{W+|fr|braise}} {{m}} * {{Z|ka}}: {{W-|ka|მღვივარი ნახშირი|tr=mġvivari naxširi}}, {{W-|ka|ცხელი ნაცარი|tr=tsxeli natsari}} * {{Z|nl}}: {{W+|nl|sintel}} * {{Z|io}}: {{W+|io|brezo}} * {{Z|en}}: {{W+|en|embers}}, {{W+|en|ember}}, {{W+|en|bracteole|guman=erê}}, {{W+|en|bractlet|guman=erê}}, {{W+|en|carbuncle|guman=erê}}, {{W+|en|fire-brand|guman=erê}}, {{W+|en|leafage|guman=erê}}, {{W-|en|live coal|guman=erê}}, {{W+|en|phyllome|guman=erê}}, {{W+|en|cigarette paper|guman=erê}} * {{Z|it}}: {{W+|it|brace}} {{m}} * {{Z|ca}}: {{W+|ca|brasa}} {{m}} * {{Z|la}}: {{W+|la|favilla}} {{m}} * {{Z|hu}}: {{W+|hu|zsarátnok}}; [[izzó fa]]([[darab]])/[[széndarab]], {{W+|hu|parázs}} * {{Z|ru}}: {{W+|ru|уголёк|tr=ugoljók}} {{n}}, {{W-|ru|tr=gorjáčaja zolá|горячая зола}} {{m}} * {{Z|sh}}: {{W+|sh|žar}} {{n}}, {{W+|sh|žeravica}} {{m}} * {{Z|es}}: {{W+|es|brasa}} {{m}}, {{W+|es|ascua}} {{m}} * {{Z|th}}: {{W-|th|แสงไฟในเศษฟืน|tr=săeng fai nai sèt feun}}, {{W-|th|ถ่านที่ยังคุอยู่|tr=tàan têe yang kóo yòo}}, {{W-|th|เถ้าที่ยังคุกกรุ่นอยู่|tr=tâo têe yang kóok gròon yòo}} * {{Z|tr}}: {{W+|tr|kor}}, {{W+|tr|köz}}, {{W+|tr|levha|guman=erê}}, {{W+|tr|manga|guman=erê}}, {{W+|tr|sarma|guman=erê}}, {{W+|tr|takım|guman=erê}}, {{W+|tr|talaş|guman=erê}}, {{W+|tr|talaz|guman=erê}}, {{W+|tr|tim|guman=erê}}, {{W+|tr|titrek kavak|guman=erê}}, {{W+|tr|varak|guman=erê}} {{werger-bin}} === Navdêr 3 === {{navdêr|ku|z=?}} # [[kelûpel]], [[tişt]], [[hûrûmûr]] ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|item}}, {{W+|en|goods}}, {{W+|en|wares}}, {{W+|en|products}} {{werger-bin}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza}} # [[pel]] == {{ziman|gl}} == === Navdêr === {{navdêr|gl|z=m}} # {{f|gl|anatomî}} [[çerm#ku|çerm]] == {{ziman|oc}} == === Navdêr === {{navdêr|oc|z=n}} # {{f|oc|anatomî}} [[mû#ku|mû]], [[pûrt#ku|pûrt]], [[pirç#ku|pirç]] == {{ziman|rm}} == === Navdêr === {{navdêr|rm}} # {{f|rm|anatomî}} [[çerm#ku|çerm]] 3o46l6xc82smgqskgdykd9bf84cxnf3 6241663 6241662 2026-07-11T20:31:59Z Wikihez 7344 /* Navdêr 2 */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin 6241663 wikitext text/x-wiki {{binêre herwiha/pel}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA|pʰɛl}} * {{ku-kîte}} === Navdêr 1 === {{ku-tewîn-nav|pel|nêr}} [[Wêne:Leaf 1 web.jpg|thumb|pel (1)]] {{navdêr|ku|z=n}}, {{p-ya req}} # {{maneid|ku|riwek}} [[parçe|Parçe]]yên [[çeq]]ên [[dar]]an ve [[şên]] dibin. ([[pêşî]] ji [[bişkoj]]an [[pişkivîn|dipişkivin]], [[paşî]] [[kesk]] dibin û [[talî|taliyê]] [[beyîn|dibeyin]] anku [[zer]] dibin û [[werîn|diwerin]] anku [[weşîn|diweşin]]) #: {{hevmane|ku|belçim|belçîm|bilçik|belçûm|pelçim|pelçîm|pelçûm}} # [[per]], [[kaxez]], [[weraqe]], [[belgename]] ==== Bi alfabeyên din ==== * {{ku-ar|پەل}} ==== Ji wêjeya klasîk ==== * {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Ah-i bêgavê ji dil tên me ji pêta di ceger</br>Bes tu bêfeyde nesîhet ke me dil bûye '''pelek'''}} ==== Herwiha ==== {{kol3|ku|cure=Herwiha|sernav = [https://twitter.com/wikiferheng/status/1710338730089689440 Çavkanî] | {{hw|ku|pelg||Sirûc|Bîraçik|Xelfetî}} | {{hw|ku|pel||Mêrdîn|Sêwreg|Amed|Pasûr|Çewlîg|Bazîd}} | {{hw|ku|pelçim||Botan}} | {{hw|ku|belg||Dîgor|Agirî|Wan}} | {{hw|ku|belçim||Dêrsim|Serhed}} | {{hw|ku|pelç||Hewag}} | {{hw|ku|per||Semsûr}} }} ==== Bide ber ==== {{stûn| * {{g|ku|pell}} * {{g|ku|pal}} * {{g|ku|pêl}} * {{g|ku|pil}} * {{g|ku|pîl}} * {{g|ku|pol}} * {{g|ku|pul}} * {{g|ku|pûl}} * {{g|ku|bel}} }} ==== Jê ==== {{kol3|ku|cure=Jê |pel girtin<q:lêker> |pelgirtin<q:navdêr> |pelçûn<q:navdêr> }} ==== Etîmolojî ==== Hevreha şêxbizinî ''[[welg]]'', zazakî ''[[velg]]'' * {{ji|ine-pro|ku|-}}: *'''welə'''- ("hirî, pûrt") > *'''wolko'''- ("mû, hirî, pûrt; giya; daristan") :*{{ji|ira-pro||-}}: *'''warka'''- ("belg, pel") ::{{ae}}: '''verke'''- ("belg, pel") ::{{xpr}}: '''wrgr''' ("belg, pel") ::{{pal}}: '''werg ''' ("belg, pel") ::{{sog}}: '''wrkr ''' ("belg, pel") ::{{fa}}: '''berg''' ("belg, pel") ::{{mzn}}: '''verek''' ("belg, pel") ::{{ku}}: '''belg > pelg > pel''' ::{{zza}}: '''[[velg]]''' ("belg, pel") :{{sa}}: '''velke'''- ("[[per]], [[bask]]") ... :{{la}}: '''vellus'''- ("hirî, pûrt") :{{de}}: '''Wolle'''- ("hirî, pûrt") :{{en}}: '''wool'''- ("hirî, pûrt") ;{{biçûk|Çavkanî: * {{Horn|r=47}} * {{Lubotsky|r=98}} * {{Pokorny|r=1139}} }} ==== Bi zaravayên din ==== * soranî/erdelanî: gella, pelk * zazakî/kirmanckî: pel, pelçim, pure, velg, * kelhûrî/feylî/şêxbizinî: welg, welneg, werg, belg, berg, pelg * hewramî/şebekî: welg ==== Werger ==== {{werger-ser|riwek|id=riwek}} * {{Z|ab}}: {{W-|ab|абӷьы}} * {{Z|ace}}: {{W-|ace|ôn}} * {{Z|ady}}: {{W-|ady|тхьэпкӏэ}} * {{Z|aa}}: {{W-|aa|dalaa}} * {{Z|af}}: {{W+|af|blaar}} * {{Z|akl}}: {{W-|akl|dahon}} * {{Z|sq}}: {{W+|sq|gjethe|m-p}} * {{Z|pdc}}: {{W-|pdc|Blatt|nt}} * {{Z|de}}: {{W+|de|Blatt|nt}}, {{W+|de|Laubblatt|nt}} *: {{Z|gsw}}: {{W-|gsw|Blatt|nt}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Blatt|nt}} * {{Z|ryn}}: {{W-|ryn|葉|tr=はー, hā}} * {{Z|ams}}: {{W-|ams|葉|tr=はー, hā}} * {{Z|am}}: {{W-|am|ቅጠል}} * {{Z|an}}: {{W+|an|fuella|m}} * {{Z|arc}}: *: {{Z|syc}}: {{W-|syc|ܛܪܦܐ|n|tr=ṭarpā}} * {{Z|agj}}: {{W-|agj|ቅጠል|tr=qəțäl}} * {{Z|rup}}: {{W-|rup|frãndzã|m}}, {{W-|rup|frundzã|m}} * {{Z|as}}: {{W-|as|পাত|nt}} * {{Z|bno}}: {{W-|bno|rahon}}, {{W-|bno|dahon}} * {{Z|ast}}: {{W+|ast|fueya|m}} * {{Z|ask}}: {{W-|ask|pār}} * {{Z|tay}}: {{W-|tay|abau}} * {{Z|ay}}: {{W+|ay|laphi}} * {{Z|ain}}: {{W-|ain|ハㇺ|tr=ham}} * {{Z|az}}: {{W+|az|yarpaq}} * {{Z|bdq}}: {{W-|bdq|hla}} * {{Z|ban}}: {{W-|ban|don}} * {{Z|eu}}: {{W+|eu|hosto}}, {{W+|eu|orri}} * {{Z|ba}}: {{W-|ba|япраҡ}} * {{Z|be}}: {{W-|be|ліст|n}} * {{Z|bn}}: {{W+|bn|পাতা}} * {{Z|bho}}: {{W-|bho|पान}} * {{Z|bol}}: {{W-|bol|kumi rewe}} * {{Z|br}}: {{W+|br|delienn|m}} * {{Z|kxd}}: {{W-|kxd|daun}} * {{Z|bug}}: {{W-|bug|daung}} * {{Z|bg}}: {{W+|bg|лист|n}}, {{W+|bg|листо́|nt}} * {{Z|my}}: {{W+|my|အရွက်}} * {{Z|bua}}: {{W-|bua|набша}}, {{W-|bua|набшаһан}}, {{W-|bua|намаа}} * {{Z|kac}}: {{W-|kac|lap}} * {{Z|ccc}}: {{W-|ccc|chijpana}} * {{Z|cjm}}: {{W-|cjm|ꨈꨶꨮꩉ}}, {{W-|cjm|ꨨꨤꨩ}} * {{Z|cbk}}: {{W-|cbk|ohas}} * {{Z|ce}}: {{W-|ce|гӏа}} * {{Z|cs}}: {{W+|cs|list|n}} * {{Z|chr}}: {{W-|chr|ᎤᎦᎶᎬ}} * {{Z|ny}}: {{W-|ny|tsamba}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|葉|tr=jip6}}, {{W-|yue|葉子|tr=jip6 zi2}} *: {{Z|dng}}: {{W-|dng|еезы}}, {{W-|dng|еер}}, {{W-|dng|езы}} *: {{Z|hak}}: {{W-|hak|葉|tr=ya̍p}} *: {{Z|cjy}}: {{W-|cjy|葉子|tr=ieh4 zeh}} *: {{Z|cmn}}: {{W+|cmn|葉|tr=yè}}, {{W+|cmn|葉子|tr=yèzi}} *: {{Z|cdo}}: {{W-|cdo|箬箬|tr=niŏh-niŏh}} *: {{Z|nan}}: {{W+|nan|葉|tr=ia̍p}}, {{W+|nan|葉仔|tr=hio̍h-á}} *: {{Z|wuu}}: {{W-|wuu|葉}}, {{W-|wuu|葉子}} *: {{Z|hsn}}: {{W-|hsn|葉子|tr=ie6 zr}} * {{Z|cv}}: {{W-|cv|ҫулҫӑ}} * {{Z|dlm}}: {{W-|dlm|fualja|m}} * {{Z|da}}: {{W+|da|blad|nt}}, {{W-|da|løv|nt}} * {{Z|duu}}: {{W-|duu|vng'lvp}} * {{Z|id}}: {{W+|id|daun}} * {{Z|enq}}: {{W-|enq|yoko}} * {{Z|ar}}: {{W-|ar|وَرَقَة|m}} * {{Z|hy}}: {{W-|hy|տերեւ}} * {{Z|myv}}: {{W-|myv|лопа}} * {{Z|eo}}: {{W+|eo|folio}} * {{Z|et}}: {{W+|et|leht}} * {{Z|gez}}: {{W-|gez|ቈጽል}} * {{Z|eve}}: {{W-|eve|эбдэнрэ}} * {{Z|evn}}: {{W-|evn|авданна}} * {{Z|ee}}: {{W-|ee|aŋgba}} * {{Z|fa}}: {{W+|fa|برگ|tr=barg}} * {{Z|fo}}: {{W-|fo|blað|nt}} * {{Z|fj}}: {{W+|fj|drau}} * {{Z|fi}}: {{W+|fi|lehti}} * {{Z|fon}}: {{W-|fon|ama}} * {{Z|frp}}: {{W-|frp|fôlye|m}} * {{Z|fro}}: {{W-|fro|fueille|m}} * {{Z|fr}}: {{W+|fr|feuille|m}} * {{Z|fur}}: {{W-|fur|fuee|m}} * {{Z|stq}}: {{W-|stq|Blääd|nt}} * {{Z|fy}}: {{W-|fy|blêd}} * {{Z|ff}}: *: Latînî: {{W-|ff|haako}}, {{W-|ff|kaakol}} *: Adlamî: {{W-|ff|𞤸𞤢𞥄𞤳𞤮}}, {{W-|ff|𞤳𞤢𞥄𞤳𞤮𞤤}} * {{Z|fuy}}: {{W-|fuy|hutu}} * {{Z|gd}}: {{W-|gd|duille|m}}, {{W-|gd|duilleag|m}} * {{Z|gl}}: {{W+|gl|folla|m}} * {{Z|glk}}: {{W-|glk|ولگ}} * {{Z|gu}}: {{W-|gu|પાન|m}}, {{W-|gu|પર્ણ|nt}}, {{W-|gu|પાંદડું|nt}}, {{W-|gu|દલ}} * {{Z|ka}}: {{W+|ka|ფოთოლი}} * {{Z|gn}}: {{W+|gn|togue}} * {{Z|gwi}}: {{W-|gwi|chʼatʼan}} * {{Z|ht}}: {{W-|ht|fèy}} * {{Z|haw}}: {{W-|haw|lau}} * {{Z|ha}}: {{W+|ha|ganye}}, {{W-|ha|warƙa}} * {{Z|mba}}: {{W-|mba|dahon}} * {{Z|hi}}: {{W+|hi|पत्ता|n}}, {{W+|hi|पत्ती|m}} * {{Z|ho}}: {{W-|ho|raurau}} * {{Z|hil}}: {{W-|hil|dahon}} * {{Z|meu}}: {{W-|meu|rau}} * {{Z|mww}}: {{W-|mww|nplooj}} * {{Z|nl}}: {{W+|nl|blad|nt}} * {{Z|hop}}: {{W-|hop|nàapi}} * {{Z|he}}: {{W+|he|עָלֶה|n|tr=alé}} * {{Z|io}}: {{W+|io|folio}} * {{Z|ig}}: {{W-|ig|akwụkwọ}} * {{Z|inz}}: {{W-|inz|qap}} * {{Z|ang}}: {{W+|ang|lēaf|nt}} * {{Z|en}}: {{W+|en|leaf}} * {{Z|izh}}: {{W-|izh|lehti}} * {{Z|ia}}: {{W-|ia|folio}} * {{Z|iu}}: {{W-|iu|ᐊᑭᕈᐊᕈᖅ}} * {{Z|ill}}: {{W-|ill|raun}} * {{Z|ga}}: {{W+|ga|duilleog|m}}, {{W+|ga|bileog|m}} * {{Z|it}}: {{W+|it|foglia|m}} * {{Z|ium}}: {{W-|ium|normh}} * {{Z|is}}: {{W+|is|lauf|nt}}, {{W+|is|laufblað|nt}} * {{Z|ja}}: {{W+|ja|葉|tr=は, ha}}, {{W+|ja|葉っぱ|tr=はっぱ, happa}}, {{W+|ja|木の葉|tr=このは, konoha}} * {{Z|jra}}: {{W-|jra|hla}} * {{Z|kaw}}: {{W-|kaw|ron}} * {{Z|jv}}: {{W+|jv|godhong}}, {{W-|jv|ron}} * {{Z|kl}}: {{W-|kl|pilu}} * {{Z|bsh}}: {{W-|bsh|por}} * {{Z|kn}}: {{W+|kn|ಎಲೆ}} * {{Z|pam}}: {{W-|pam|bulung}} * {{Z|krl}}: {{W-|krl|lehti}} * {{Z|csb}}: {{W-|csb|lëst}} * {{Z|ca}}: {{W+|ca|fulla|m}} * {{Z|qu}}: {{W-|qu|raphi}}, {{W-|qu|llaqhi}} * {{Z|kha}}: {{W-|kha|sla}} * {{Z|kzg}}: {{W-|kzg|葉|tr=ぱー, pā}} * {{Z|ky}}: {{W+|ky|жалбырак}} * {{Z|ki}}: {{W-|ki|ithangũ|c5}} * {{Z|si}}: {{W-|si|කොළේ}}, {{W-|si|කොළය}} * {{Z|kyi}}: {{W-|kyi|dun}} * {{Z|koi}}: {{W-|koi|кор}} * {{Z|swb}}: {{W-|swb|wani|c11|c6}} * {{Z|kok}}: {{W-|kok|पाल्लो|tr=pāllo}} * {{Z|ko}}: {{W+|ko|잎}} * {{Z|co}}: {{W+|co|foglia|m}} * {{Z|cr}}: *: {{Z|crk}}: {{W-|crk|nīpiy}} * {{Z|xug}}: {{W-|xug|葉|tr=ぱー, phā}} * {{Z|lad}}: {{W-|lad|foja|m}}, {{W-|lad|yaprak|n}} * {{Z|lkt}}: {{W-|lkt|wahpe}}, {{W-|lkt|ape}} * {{Z|ltg}}: {{W-|ltg|lopa|m}} * {{Z|la}}: {{W+|la|folium|nt}}, {{W-|la|frons|m}} * {{Z|lv}}: {{W+|lv|lapa|m}} * {{Z|lo}}: {{W-|lo|ໃບ}}, {{W+|lo|ໃບໄມ້}} * {{Z|ln}}: {{W-|ln|nkásá|c9|c10}}, {{W-|ln|lokásá|c11|c10}} * {{Z|lij}}: {{W-|lij|féuggia|m}} * {{Z|li}}: {{W+|li|louf|nt}} * {{Z|lt}}: {{W+|lt|lapas|n}} * {{Z|lmo}}: {{W-|lmo|foeuja|m}}, {{W-|lmo|fòia|m}} * {{Z|lg}}: {{W-|lg|ekikoola}} * {{Z|luy}}: {{W-|luy|lisafu}} * {{Z|lb}}: {{W-|lb|Blat|nt}} * {{Z|mhn}}: {{W-|mhn|lap|nt}} * {{Z|mdh}}: {{W-|mdh|laun}} * {{Z|mk}}: {{W-|mk|лист|n}} * {{Z|mg}}: {{W+|mg|ravina}}, {{W+|mg|ravina}} * {{Z|ml}}: {{W+|ml|ഇല}} * {{Z|ms}}: {{W+|ms|daun}} * {{Z|mt}}: {{W-|mt|werqa|m}} * {{Z|mnc}}: {{W-|mnc|ᠠᠪᡩᠠᡥᠠ}} * {{Z|gv}}: {{W-|gv|duillag|m}} * {{Z|mns-nor}}: {{W-|mns-nor|лӯпта}} * {{Z|mi}}: {{W+|mi|rau}}, {{W-|mi|tawhera}} * {{Z|mrw}}: {{W-|mrw|ra'on}} * {{Z|mr}}: {{W-|mr|पर्ण|nt}}, {{W+|mr|पत्र|nt}}, {{W+|mr|दल|nt}} * Marî: *: {{Z|mhr}}: {{W-|mhr|лышташ}} *: {{Z|mrj}}: {{W-|mrj|ӹлӹштӓш}} * {{Z|gun}}: {{W-|gun|ogue}} * {{Z|hu}}: {{W+|hu|levél}}, {{W+|hu|falevél}} * {{Z|mel}}: {{W-|mel|daun}} * {{Z|egy}}: {{W-egy|gꜣbt|h=g-A-b-t-Hn:Z2ss}} * {{Z|mvi}}: {{W-|mvi|葉|tr=ぱー, pā}} * {{Z|lus}}: {{W-|lus|hnah}} * {{Z|min}}: {{W-|min|daun}} * {{Z|mwl}}: {{W-|mwl|fuolha|m}} * {{Z|xpq}}: {{W-|xpq|wunipaq}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|навч}} *: Mongolî: {{W-|mn|ᠨᠠᠪᠴᠢ}} * {{Z|mnw}}: {{W-|mnw|သၠ|tr=hlaˀ}} * {{Z|mtq}}: {{W-|mtq|lả}} * {{Z|nah}}: {{W+|nah|izhuatl}} * {{Z|gld}}: {{W-|gld|хабдата}} * {{Z|nv}}: {{W-|nv|atʼąąʼ}} * {{Z|nds}}: *: {{Z|nds-de}}: {{W-|nds-de|Blatt|nt}} * {{Z|ne}}: {{W+|ne|पात}} * {{Z|ncb}}: {{W-|ncb|dai}} * {{Z|nrf}}: {{W-|nrf|fielle|m}}, {{W-|nrf|fieille|m}}, {{W-|nrf|fuule|m}}, {{W-|nrf|fiëly|m}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|blad|nt}}, {{W+|nb|løv|nt}} *: {{Z|nn}}: {{W-|nn|blad|nt}}, {{W-|nn|lauv|nt}} * {{Z|oj}}: {{W-|oj|aniibiishibag}}, {{W-|oj|aniibiishibagoon|p}}, {{W-|oj|aniibiish}}, {{W-|oj|aniibiishan|p}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᐟ|tr=aniibiishibag}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᑯᐣ|p|tr=aniibiishibagoon}}, {{W-|oj|ᐊᓂᐱᐦᐡ|tr=aniibiish}}, {{W-|oj|ᐊᓂᐱᐦᔕᐣ|p|tr=aniibiishan}} * {{Z|okn}}: {{W-|okn|葉|tr=はー, fā}} * {{Z|ryu}}: {{W-|ryu|葉|tr=ふぁー, fā}} * {{Z|oc}}: {{W+|oc|fuèlha|m}} * {{Z|one}}: {{W-|one|onláhte̲’}} * {{Z|or}}: {{W+|or|ପତ୍ର}} * {{Z|osa}}: {{W-|osa|žąąpé}} * {{Z|os}}: {{W-|os|сыф}} * {{Z|ota}}: {{W-|ota|یپراق|tr=yaprak}} * {{Z|ug}}: {{W-|ug|يوپۇرماق}}, {{W-|ug|ياپراق}} * {{Z|uz}}: {{W+|uz|yaproq}}, {{W+|uz|barg}} * {{Z|pac}}: {{W-|pac|ula}}, {{W-|pac|ila}} * {{Z|pau}}: {{W-|pau|llel}} * Pali: *: {{Z|pi}}: {{W-|pi|ပဏ္ဏ|nt}} *: {{Z|pi}}: {{W-|pi|पण्ण|nt}} *: {{Z|pi}}: {{W-|pi|បណ្ណ|nt}} *: Latînî: {{W-|pi|paṇṇa|nt}} *: {{Z|pi}}: {{W-|pi|පණ්ණ|nt}} *: {{Z|pi}}: {{W-|pi|ปณฺณ|nt}} * {{Z|pap}}: {{W-|pap|foya}} * {{Z|bxd}}: {{W-|bxd|a³¹faʔ⁵⁵}}, {{W-|bxd|sak⁵⁵ faʔ⁵⁵}} * {{Z|ps}}: {{W+|ps|پاڼه|m|tr=pâṇa}} * {{Z|pms}}: {{W-|pms|feuja|m}} * {{Z|ppl}}: {{W-|ppl|iswat}}, {{W-|ppl|izhuat}} * {{Z|pdt}}: {{W-|pdt|Blaut|nt}} * {{Z|pl}}: {{W+|pl|liść|n}} * {{Z|pt}}: {{W+|pt|folha|m}} * {{Z|prn}}: {{W-|prn|pārag}} * {{Z|pa}}: {{W-|pa|ਪੱਤਾ|n}} * {{Z|kk}}: {{W-|kk|жапырақ}} * {{Z|rap}}: {{W-|rap|rua}} * {{Z|rhg}}: {{W-|rhg|fata}} * {{Z|rgn}}: {{W-|rgn|fója|m}} * {{Z|rm}}: {{W-|rm|fegl}} * {{Z|rom}}: {{W-|rom|patrin|m}} * {{Z|ro}}: {{W+|ro|frunză|m}} * {{Z|ru}}: {{W+|ru|лист|n}}, plural for this sense: {{W+|ru|ли́стья|n-p}} * {{Z|ksw}}: {{W-|ksw|သ့ၣ်လၣ်}} * {{Z|ssy}}: {{W-|ssy|dharhaa}} * {{Z|se}}: {{W-|se|lasta}} * {{Z|sm}}: {{W-|sm|lau}} * {{Z|sa}}: {{W+|sa|पर्ण|tr=parṇá|nt}}, {{W+|sa|पत्र|nt}} * {{Z|sc}}: {{W-|sc|fògia|m}} * {{Z|ceb}}: {{W-|ceb|dahon}} * {{Z|sea}}: {{W-|sea|sela}} * {{Z|scn}}: {{W+|scn|fogghia|m}} * {{Z|sd}}: {{W-|sd|پن|n|tr=panu|cuda=پَنُ}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|лист|n}}, {{W-|sh|лиска|m}} *: Latînî: {{W+|sh|list|n}}, {{W+|sh|liska|m}} * {{Z|cu}}: *: Kirîlî: {{W-|cu|листъ|n}} *: Glagolîtîk: {{W-|cu|ⰾⰹⱄⱅⱏ|n}} * {{Z|orv}}: {{W-|orv|листъ|n}} * {{Z|sk}}: {{W+|sk|list|n}} * {{Z|sl}}: {{W+|sl|list|n}} * {{Z|zlw-slv}}: {{W-|zlw-slv|lȧ̃st|n}} * {{Z|so}}: {{W+|so|caleen|m}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|list|n}} *: {{Z|hsb}}: {{W-|hsb|list|n}} * {{Z|es}}: {{W+|es|hoja|m}} * {{Z|su}}: {{W+|su|daun}} * {{Z|sw}}: {{W+|sw|jani|c5|c6}}, {{W+|sw|msahafu|c3|c4}} * {{Z|sv}}: {{W+|sv|blad|nt}}, {{W+|sv|löv|nt}} * {{Z|shn}}: {{W-|shn|မႂ်}}, {{W-|shn|ဝႂ်}} * {{Z|zdj}}: {{W-|zdj|wani|c11|c10}} * {{Z|sn}}: {{W-|sn|shizha}} * {{Z|tg}}: {{W+|tg|барг}} * {{Z|tl}}: {{W+|tl|dahon}} * {{Z|tly}}: {{W-|tly|لیو}} * {{Z|ta}}: {{W+|ta|இலை}} * {{Z|twf}}: {{W-|twf|ə̂na}} * {{Z|roa-tar}}: {{W-|roa-tar|fogghie|m}} * {{Z|rif}}: {{W-|rif|afar|n}}, {{W-|rif|tifrešt|m}} * {{Z|tsg}}: {{W-|tsg|dahun}} * {{Z|th}}: {{W+|th|ใบ}}, {{W+|th|ใบไม้}} * {{Z|te}}: {{W+|te|ఆకు}} * {{Z|tzm}}: {{W-|tzm|ⵉⴼⴻⵔ|n}} * {{Z|tea}}: {{W-|tea|sela}} * {{Z|tt}}: {{W+|tt|яфрак}} * {{Z|tet}}: {{W-|tet|roo}} * {{Z|tr}}: {{W+|tr|yaprak}} * {{Z|tk}}: {{W-|tk|ýaprak}} * {{Z|bo}}: {{W-|bo|ལོ་མ།}} * {{Z|tli}}: {{W-|tli|kayaaní}} * {{Z|tpi}}: {{W-|tpi|lip}} * {{Z|tkn}}: {{W-|tkn|葉|tr=はー, hā}} * {{Z|xto}}: {{W-|xto|pält}} * {{Z|txb}}: {{W-|txb|pilta}} * {{Z|trm}}: {{W-|trm|påṭ}} * {{Z|tcy}}: {{W-|tcy|ಅಡಿಪಿರೆ}} * {{Z|tvl}}: {{W-|tvl|lau}} * {{Z|tpw}}: {{W-|tpw|oba}} * {{Z|udi}}: {{W-|udi|хазал}} * {{Z|udm}}: {{W-|udm|куар}} * {{Z|ur}}: {{W-|ur|پتی|m|tr=patti}} * {{Z|uk}}: {{W+|uk|лист|n}} * {{Z|vec}}: {{W+|vec|foja|m}}, {{W-|vec|fogia|m}} * {{Z|vep}}: {{W-|vep|leht}} * {{Z|vi}}: {{W+|vi|lá}} * {{Z|vo}}: {{W+|vo|bled}} * {{Z|vor}}: {{W-|vor|leht'}} * {{Z|vot}}: {{W-|vot|lehti}} * {{Z|wbk}}: {{W-|wbk|poṭ}} * {{Z|wa}}: {{W+|wa|foye|m}} * {{Z|war}}: {{W-|war|dáhon}} * {{Z|cy}}: {{W+|cy|deilen|m}} * {{Z|wym}}: {{W-|wym|błot|nt}} * {{Z|wo}}: {{W+|wo|xob}} * {{Z|km}}: {{W+|km|ស្លឹក}}, {{W-|km|ស្លឹកឈើ}} * {{Z|xh}}: {{W-|xh|igqabi|c5|c6}} * {{Z|rys}}: {{W-|rys|葉|tr=ぱー, pā}} * {{Z|sah}}: {{W-|sah|сэбирдэх}} * {{Z|yag}}: {{W-|yag|Suka}} * {{Z|yi}}: {{W-|yi|בלאַט|n|m}} * {{Z|yoi}}: {{W-|yoi|葉|tr=はー, hā}} * {{Z|yox}}: {{W-|yox|葉|tr=ぱー, pā}} * {{Z|yo}}: {{W-|yo|ewé}} * {{Z|el}}: {{W+|el|φύλλο|nt}} *: Kevn: {{W-|grc|φύλλον|nt}}, {{W-|grc|πέταλον|nt}} * {{Z|zea}}: {{W-|zea|blad|nt}} * {{Z|za}}: {{W-|za|mbaw}} * {{Z|zu}}: {{W+|zu|ikhasi|c5|c6}}, {{W+|zu|iqabi|c5|c6}} {{werger-bin}} :{{werger çavkanî|en|leaf|beş=Ev qismê Wergerê|oldid=76702326}} {{werger-ser|per, kaxez, weraqe, belgename}} * {{Z|de}}: {{W+|de|Laub}} {{n}}, {{W+|de|Seite}} {{m}}, {{W+|de|Wedel|guman=erê}} {{n}} * {{Z|fa}}: {{W+|fa|برگ}}, {{W+|fa|سند}}, {{W+|fa|صفحه}}, {{W+|fa|برگه|guman=erê}}, {{W-|fa|شراره آتش|guman=erê}}, {{W+|fa|کاغذ|guman=erê}}, {{W+|fa|مدرک|guman=erê}} * {{Z|en}}: {{W+|en|covey}}, {{W+|en|foliage}}, {{W+|en|frond}}, {{W+|en|gleed}}, {{W+|en|platoon}}, {{W+|en|file}}, {{W+|en|phyllo-}} * {{Z|tr}}: {{W+|tr|belge}}, {{W+|tr|çalkantı}}, {{W+|tr|çapak}}, {{W+|tr|lahza|guman=erê}} {{werger-bin}} === Navdêr 2 === [[Wêne:Embers 01.JPG|thumb|250px|pel (2)]] {{navdêr|ku|z=n}} # [[parçe|Parçe]]yên [[agir]]î yên ji [[pirt]]ên [[dar]]î yan [[kumir]]ê yên ku agirî girtine û dişewitin lê hê nebûne [[xwelî]]. #: {{hevmane|ku|pêt}} ==== Bi alfabeyên din ==== * {{ku-ar|په‌ل}} ==== Herwiha ==== * {{g|ku|pêlox}} * {{g|ku|pêreng}} * {{g|ku|piring}} * {{g|ku|piloxt}} ==== Etîmolojî ==== Herwiha [[piring]], [[pêreng]], ji {{ji|ine-pro|ku|*péh₂ur|t=[[agir]]}}. Hevreha çekî [[pýř]] (pel), {{hv|grc|πῦρ}} (pûr: agir > kurdî [[pîroman]]), [[toxarî]] A ''por'' (agir), toxarî B ''puwar'' (agir), hîtîtî ''paḫḫur'' ([[agir]]), danmarkî / norwecî / {{hv|sv|fyr}} (agir), îngilîzî [[fire]] (agir), {{hv|hy|հուր}} (hur: agir)... ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Glut}} {{m}} * {{Z|zh}}: *: [[mandarînî]]: {{W+|cmn|餘燼|sc=Hani|xs=Mandarin}}, {{W+|cmn|余烬|tr=yújìn|sc=Hani|xs=Mandarin}} * {{Z|ar}}: {{W-|ar|جمرة|tr=cemre}} * {{Z|hy}}: {{W-|hy|մարմրող ածուխ|tr=marmroġ açux}} * {{Z|eo}}: {{W-|eo|braĝo|xs=Esperanto}}, {{W-|eo|ardaĵo|xs=Esperanto}} * {{Z|fa}}: {{W+|fa|شعله|sc=fa-Arab}} * {{Z|fi}}: {{W+|fi|kekäle}} * {{Z|fr}}: {{W+|fr|braise}} {{m}} * {{Z|ka}}: {{W-|ka|მღვივარი ნახშირი|tr=mġvivari naxširi}}, {{W-|ka|ცხელი ნაცარი|tr=tsxeli natsari}} * {{Z|nl}}: {{W+|nl|sintel}} * {{Z|io}}: {{W+|io|brezo}} * {{Z|en}}: {{W+|en|embers}}, {{W+|en|ember}}, {{W+|en|bracteole|guman=erê}}, {{W+|en|bractlet|guman=erê}}, {{W+|en|carbuncle|guman=erê}}, {{W+|en|fire-brand|guman=erê}}, {{W+|en|leafage|guman=erê}}, {{W-|en|live coal|guman=erê}}, {{W+|en|phyllome|guman=erê}}, {{W+|en|cigarette paper|guman=erê}} * {{Z|it}}: {{W+|it|brace}} {{m}} * {{Z|ca}}: {{W+|ca|brasa}} {{m}} * {{Z|la}}: {{W+|la|favilla}} {{m}} * {{Z|hu}}: {{W+|hu|zsarátnok}}; [[izzó fa]]([[darab]])/[[széndarab]], {{W+|hu|parázs}} * {{Z|ru}}: {{W+|ru|уголёк|tr=ugoljók}} {{n}}, {{W-|ru|tr=gorjáčaja zolá|горячая зола}} {{m}} * {{Z|sh}}: {{W+|sh|žar}} {{n}}, {{W+|sh|žeravica}} {{m}} * {{Z|es}}: {{W+|es|brasa}} {{m}}, {{W+|es|ascua}} {{m}} * {{Z|th}}: {{W-|th|แสงไฟในเศษฟืน|tr=săeng fai nai sèt feun}}, {{W-|th|ถ่านที่ยังคุอยู่|tr=tàan têe yang kóo yòo}}, {{W-|th|เถ้าที่ยังคุกกรุ่นอยู่|tr=tâo têe yang kóok gròon yòo}} * {{Z|tr}}: {{W+|tr|kor}}, {{W+|tr|köz}}, {{W+|tr|levha|guman=erê}}, {{W+|tr|manga|guman=erê}}, {{W+|tr|sarma|guman=erê}}, {{W+|tr|takım|guman=erê}}, {{W+|tr|talaş|guman=erê}}, {{W+|tr|talaz|guman=erê}}, {{W+|tr|tim|guman=erê}}, {{W+|tr|titrek kavak|guman=erê}}, {{W+|tr|varak|guman=erê}} {{werger-bin}} === Navdêr 3 === {{navdêr|ku|z=?}} # [[kelûpel]], [[tişt]], [[hûrûmûr]] ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|item}}, {{W+|en|goods}}, {{W+|en|wares}}, {{W+|en|products}} {{werger-bin}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza}} # [[pel]] == {{ziman|gl}} == === Navdêr === {{navdêr|gl|z=m}} # {{f|gl|anatomî}} [[çerm#ku|çerm]] == {{ziman|oc}} == === Navdêr === {{navdêr|oc|z=n}} # {{f|oc|anatomî}} [[mû#ku|mû]], [[pûrt#ku|pûrt]], [[pirç#ku|pirç]] == {{ziman|rm}} == === Navdêr === {{navdêr|rm}} # {{f|rm|anatomî}} [[çerm#ku|çerm]] o83xivdn0sexmgx6b8qjmbcje10hgj6 6241664 6241663 2026-07-11T20:32:39Z Wikihez 7344 /* Werger */ 6241664 wikitext text/x-wiki {{binêre herwiha/pel}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA|pʰɛl}} * {{ku-kîte}} === Navdêr 1 === {{ku-tewîn-nav|pel|nêr}} [[Wêne:Leaf 1 web.jpg|thumb|pel (1)]] {{navdêr|ku|z=n}}, {{p-ya req}} # {{maneid|ku|riwek}} [[parçe|Parçe]]yên [[çeq]]ên [[dar]]an ve [[şên]] dibin. ([[pêşî]] ji [[bişkoj]]an [[pişkivîn|dipişkivin]], [[paşî]] [[kesk]] dibin û [[talî|taliyê]] [[beyîn|dibeyin]] anku [[zer]] dibin û [[werîn|diwerin]] anku [[weşîn|diweşin]]) #: {{hevmane|ku|belçim|belçîm|bilçik|belçûm|pelçim|pelçîm|pelçûm}} # [[per]], [[kaxez]], [[weraqe]], [[belgename]] ==== Bi alfabeyên din ==== * {{ku-ar|پەل}} ==== Ji wêjeya klasîk ==== * {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Ah-i bêgavê ji dil tên me ji pêta di ceger</br>Bes tu bêfeyde nesîhet ke me dil bûye '''pelek'''}} ==== Herwiha ==== {{kol3|ku|cure=Herwiha|sernav = [https://twitter.com/wikiferheng/status/1710338730089689440 Çavkanî] | {{hw|ku|pelg||Sirûc|Bîraçik|Xelfetî}} | {{hw|ku|pel||Mêrdîn|Sêwreg|Amed|Pasûr|Çewlîg|Bazîd}} | {{hw|ku|pelçim||Botan}} | {{hw|ku|belg||Dîgor|Agirî|Wan}} | {{hw|ku|belçim||Dêrsim|Serhed}} | {{hw|ku|pelç||Hewag}} | {{hw|ku|per||Semsûr}} }} ==== Bide ber ==== {{stûn| * {{g|ku|pell}} * {{g|ku|pal}} * {{g|ku|pêl}} * {{g|ku|pil}} * {{g|ku|pîl}} * {{g|ku|pol}} * {{g|ku|pul}} * {{g|ku|pûl}} * {{g|ku|bel}} }} ==== Jê ==== {{kol3|ku|cure=Jê |pel girtin<q:lêker> |pelgirtin<q:navdêr> |pelçûn<q:navdêr> }} ==== Etîmolojî ==== Hevreha şêxbizinî ''[[welg]]'', zazakî ''[[velg]]'' * {{ji|ine-pro|ku|-}}: *'''welə'''- ("hirî, pûrt") > *'''wolko'''- ("mû, hirî, pûrt; giya; daristan") :*{{ji|ira-pro||-}}: *'''warka'''- ("belg, pel") ::{{ae}}: '''verke'''- ("belg, pel") ::{{xpr}}: '''wrgr''' ("belg, pel") ::{{pal}}: '''werg ''' ("belg, pel") ::{{sog}}: '''wrkr ''' ("belg, pel") ::{{fa}}: '''berg''' ("belg, pel") ::{{mzn}}: '''verek''' ("belg, pel") ::{{ku}}: '''belg > pelg > pel''' ::{{zza}}: '''[[velg]]''' ("belg, pel") :{{sa}}: '''velke'''- ("[[per]], [[bask]]") ... :{{la}}: '''vellus'''- ("hirî, pûrt") :{{de}}: '''Wolle'''- ("hirî, pûrt") :{{en}}: '''wool'''- ("hirî, pûrt") ;{{biçûk|Çavkanî: * {{Horn|r=47}} * {{Lubotsky|r=98}} * {{Pokorny|r=1139}} }} ==== Bi zaravayên din ==== * soranî/erdelanî: gella, pelk * zazakî/kirmanckî: pel, pelçim, pure, velg, * kelhûrî/feylî/şêxbizinî: welg, welneg, werg, belg, berg, pelg * hewramî/şebekî: welg ==== Werger ==== {{werger-ser|parçeyên çeqên daran ve şên dibin|id=riwek}} * {{Z|ab}}: {{W-|ab|абӷьы}} * {{Z|ace}}: {{W-|ace|ôn}} * {{Z|ady}}: {{W-|ady|тхьэпкӏэ}} * {{Z|aa}}: {{W-|aa|dalaa}} * {{Z|af}}: {{W+|af|blaar}} * {{Z|akl}}: {{W-|akl|dahon}} * {{Z|sq}}: {{W+|sq|gjethe|m-p}} * {{Z|pdc}}: {{W-|pdc|Blatt|nt}} * {{Z|de}}: {{W+|de|Blatt|nt}}, {{W+|de|Laubblatt|nt}} *: {{Z|gsw}}: {{W-|gsw|Blatt|nt}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Blatt|nt}} * {{Z|ryn}}: {{W-|ryn|葉|tr=はー, hā}} * {{Z|ams}}: {{W-|ams|葉|tr=はー, hā}} * {{Z|am}}: {{W-|am|ቅጠል}} * {{Z|an}}: {{W+|an|fuella|m}} * {{Z|arc}}: *: {{Z|syc}}: {{W-|syc|ܛܪܦܐ|n|tr=ṭarpā}} * {{Z|agj}}: {{W-|agj|ቅጠል|tr=qəțäl}} * {{Z|rup}}: {{W-|rup|frãndzã|m}}, {{W-|rup|frundzã|m}} * {{Z|as}}: {{W-|as|পাত|nt}} * {{Z|bno}}: {{W-|bno|rahon}}, {{W-|bno|dahon}} * {{Z|ast}}: {{W+|ast|fueya|m}} * {{Z|ask}}: {{W-|ask|pār}} * {{Z|tay}}: {{W-|tay|abau}} * {{Z|ay}}: {{W+|ay|laphi}} * {{Z|ain}}: {{W-|ain|ハㇺ|tr=ham}} * {{Z|az}}: {{W+|az|yarpaq}} * {{Z|bdq}}: {{W-|bdq|hla}} * {{Z|ban}}: {{W-|ban|don}} * {{Z|eu}}: {{W+|eu|hosto}}, {{W+|eu|orri}} * {{Z|ba}}: {{W-|ba|япраҡ}} * {{Z|be}}: {{W-|be|ліст|n}} * {{Z|bn}}: {{W+|bn|পাতা}} * {{Z|bho}}: {{W-|bho|पान}} * {{Z|bol}}: {{W-|bol|kumi rewe}} * {{Z|br}}: {{W+|br|delienn|m}} * {{Z|kxd}}: {{W-|kxd|daun}} * {{Z|bug}}: {{W-|bug|daung}} * {{Z|bg}}: {{W+|bg|лист|n}}, {{W+|bg|листо́|nt}} * {{Z|my}}: {{W+|my|အရွက်}} * {{Z|bua}}: {{W-|bua|набша}}, {{W-|bua|набшаһан}}, {{W-|bua|намаа}} * {{Z|kac}}: {{W-|kac|lap}} * {{Z|ccc}}: {{W-|ccc|chijpana}} * {{Z|cjm}}: {{W-|cjm|ꨈꨶꨮꩉ}}, {{W-|cjm|ꨨꨤꨩ}} * {{Z|cbk}}: {{W-|cbk|ohas}} * {{Z|ce}}: {{W-|ce|гӏа}} * {{Z|cs}}: {{W+|cs|list|n}} * {{Z|chr}}: {{W-|chr|ᎤᎦᎶᎬ}} * {{Z|ny}}: {{W-|ny|tsamba}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|葉|tr=jip6}}, {{W-|yue|葉子|tr=jip6 zi2}} *: {{Z|dng}}: {{W-|dng|еезы}}, {{W-|dng|еер}}, {{W-|dng|езы}} *: {{Z|hak}}: {{W-|hak|葉|tr=ya̍p}} *: {{Z|cjy}}: {{W-|cjy|葉子|tr=ieh4 zeh}} *: {{Z|cmn}}: {{W+|cmn|葉|tr=yè}}, {{W+|cmn|葉子|tr=yèzi}} *: {{Z|cdo}}: {{W-|cdo|箬箬|tr=niŏh-niŏh}} *: {{Z|nan}}: {{W+|nan|葉|tr=ia̍p}}, {{W+|nan|葉仔|tr=hio̍h-á}} *: {{Z|wuu}}: {{W-|wuu|葉}}, {{W-|wuu|葉子}} *: {{Z|hsn}}: {{W-|hsn|葉子|tr=ie6 zr}} * {{Z|cv}}: {{W-|cv|ҫулҫӑ}} * {{Z|dlm}}: {{W-|dlm|fualja|m}} * {{Z|da}}: {{W+|da|blad|nt}}, {{W-|da|løv|nt}} * {{Z|duu}}: {{W-|duu|vng'lvp}} * {{Z|id}}: {{W+|id|daun}} * {{Z|enq}}: {{W-|enq|yoko}} * {{Z|ar}}: {{W-|ar|وَرَقَة|m}} * {{Z|hy}}: {{W-|hy|տերեւ}} * {{Z|myv}}: {{W-|myv|лопа}} * {{Z|eo}}: {{W+|eo|folio}} * {{Z|et}}: {{W+|et|leht}} * {{Z|gez}}: {{W-|gez|ቈጽል}} * {{Z|eve}}: {{W-|eve|эбдэнрэ}} * {{Z|evn}}: {{W-|evn|авданна}} * {{Z|ee}}: {{W-|ee|aŋgba}} * {{Z|fa}}: {{W+|fa|برگ|tr=barg}} * {{Z|fo}}: {{W-|fo|blað|nt}} * {{Z|fj}}: {{W+|fj|drau}} * {{Z|fi}}: {{W+|fi|lehti}} * {{Z|fon}}: {{W-|fon|ama}} * {{Z|frp}}: {{W-|frp|fôlye|m}} * {{Z|fro}}: {{W-|fro|fueille|m}} * {{Z|fr}}: {{W+|fr|feuille|m}} * {{Z|fur}}: {{W-|fur|fuee|m}} * {{Z|stq}}: {{W-|stq|Blääd|nt}} * {{Z|fy}}: {{W-|fy|blêd}} * {{Z|ff}}: *: Latînî: {{W-|ff|haako}}, {{W-|ff|kaakol}} *: Adlamî: {{W-|ff|𞤸𞤢𞥄𞤳𞤮}}, {{W-|ff|𞤳𞤢𞥄𞤳𞤮𞤤}} * {{Z|fuy}}: {{W-|fuy|hutu}} * {{Z|gd}}: {{W-|gd|duille|m}}, {{W-|gd|duilleag|m}} * {{Z|gl}}: {{W+|gl|folla|m}} * {{Z|glk}}: {{W-|glk|ولگ}} * {{Z|gu}}: {{W-|gu|પાન|m}}, {{W-|gu|પર્ણ|nt}}, {{W-|gu|પાંદડું|nt}}, {{W-|gu|દલ}} * {{Z|ka}}: {{W+|ka|ფოთოლი}} * {{Z|gn}}: {{W+|gn|togue}} * {{Z|gwi}}: {{W-|gwi|chʼatʼan}} * {{Z|ht}}: {{W-|ht|fèy}} * {{Z|haw}}: {{W-|haw|lau}} * {{Z|ha}}: {{W+|ha|ganye}}, {{W-|ha|warƙa}} * {{Z|mba}}: {{W-|mba|dahon}} * {{Z|hi}}: {{W+|hi|पत्ता|n}}, {{W+|hi|पत्ती|m}} * {{Z|ho}}: {{W-|ho|raurau}} * {{Z|hil}}: {{W-|hil|dahon}} * {{Z|meu}}: {{W-|meu|rau}} * {{Z|mww}}: {{W-|mww|nplooj}} * {{Z|nl}}: {{W+|nl|blad|nt}} * {{Z|hop}}: {{W-|hop|nàapi}} * {{Z|he}}: {{W+|he|עָלֶה|n|tr=alé}} * {{Z|io}}: {{W+|io|folio}} * {{Z|ig}}: {{W-|ig|akwụkwọ}} * {{Z|inz}}: {{W-|inz|qap}} * {{Z|ang}}: {{W+|ang|lēaf|nt}} * {{Z|en}}: {{W+|en|leaf}} * {{Z|izh}}: {{W-|izh|lehti}} * {{Z|ia}}: {{W-|ia|folio}} * {{Z|iu}}: {{W-|iu|ᐊᑭᕈᐊᕈᖅ}} * {{Z|ill}}: {{W-|ill|raun}} * {{Z|ga}}: {{W+|ga|duilleog|m}}, {{W+|ga|bileog|m}} * {{Z|it}}: {{W+|it|foglia|m}} * {{Z|ium}}: {{W-|ium|normh}} * {{Z|is}}: {{W+|is|lauf|nt}}, {{W+|is|laufblað|nt}} * {{Z|ja}}: {{W+|ja|葉|tr=は, ha}}, {{W+|ja|葉っぱ|tr=はっぱ, happa}}, {{W+|ja|木の葉|tr=このは, konoha}} * {{Z|jra}}: {{W-|jra|hla}} * {{Z|kaw}}: {{W-|kaw|ron}} * {{Z|jv}}: {{W+|jv|godhong}}, {{W-|jv|ron}} * {{Z|kl}}: {{W-|kl|pilu}} * {{Z|bsh}}: {{W-|bsh|por}} * {{Z|kn}}: {{W+|kn|ಎಲೆ}} * {{Z|pam}}: {{W-|pam|bulung}} * {{Z|krl}}: {{W-|krl|lehti}} * {{Z|csb}}: {{W-|csb|lëst}} * {{Z|ca}}: {{W+|ca|fulla|m}} * {{Z|qu}}: {{W-|qu|raphi}}, {{W-|qu|llaqhi}} * {{Z|kha}}: {{W-|kha|sla}} * {{Z|kzg}}: {{W-|kzg|葉|tr=ぱー, pā}} * {{Z|ky}}: {{W+|ky|жалбырак}} * {{Z|ki}}: {{W-|ki|ithangũ|c5}} * {{Z|si}}: {{W-|si|කොළේ}}, {{W-|si|කොළය}} * {{Z|kyi}}: {{W-|kyi|dun}} * {{Z|koi}}: {{W-|koi|кор}} * {{Z|swb}}: {{W-|swb|wani|c11|c6}} * {{Z|kok}}: {{W-|kok|पाल्लो|tr=pāllo}} * {{Z|ko}}: {{W+|ko|잎}} * {{Z|co}}: {{W+|co|foglia|m}} * {{Z|cr}}: *: {{Z|crk}}: {{W-|crk|nīpiy}} * {{Z|xug}}: {{W-|xug|葉|tr=ぱー, phā}} * {{Z|lad}}: {{W-|lad|foja|m}}, {{W-|lad|yaprak|n}} * {{Z|lkt}}: {{W-|lkt|wahpe}}, {{W-|lkt|ape}} * {{Z|ltg}}: {{W-|ltg|lopa|m}} * {{Z|la}}: {{W+|la|folium|nt}}, {{W-|la|frons|m}} * {{Z|lv}}: {{W+|lv|lapa|m}} * {{Z|lo}}: {{W-|lo|ໃບ}}, {{W+|lo|ໃບໄມ້}} * {{Z|ln}}: {{W-|ln|nkásá|c9|c10}}, {{W-|ln|lokásá|c11|c10}} * {{Z|lij}}: {{W-|lij|féuggia|m}} * {{Z|li}}: {{W+|li|louf|nt}} * {{Z|lt}}: {{W+|lt|lapas|n}} * {{Z|lmo}}: {{W-|lmo|foeuja|m}}, {{W-|lmo|fòia|m}} * {{Z|lg}}: {{W-|lg|ekikoola}} * {{Z|luy}}: {{W-|luy|lisafu}} * {{Z|lb}}: {{W-|lb|Blat|nt}} * {{Z|mhn}}: {{W-|mhn|lap|nt}} * {{Z|mdh}}: {{W-|mdh|laun}} * {{Z|mk}}: {{W-|mk|лист|n}} * {{Z|mg}}: {{W+|mg|ravina}}, {{W+|mg|ravina}} * {{Z|ml}}: {{W+|ml|ഇല}} * {{Z|ms}}: {{W+|ms|daun}} * {{Z|mt}}: {{W-|mt|werqa|m}} * {{Z|mnc}}: {{W-|mnc|ᠠᠪᡩᠠᡥᠠ}} * {{Z|gv}}: {{W-|gv|duillag|m}} * {{Z|mns-nor}}: {{W-|mns-nor|лӯпта}} * {{Z|mi}}: {{W+|mi|rau}}, {{W-|mi|tawhera}} * {{Z|mrw}}: {{W-|mrw|ra'on}} * {{Z|mr}}: {{W-|mr|पर्ण|nt}}, {{W+|mr|पत्र|nt}}, {{W+|mr|दल|nt}} * Marî: *: {{Z|mhr}}: {{W-|mhr|лышташ}} *: {{Z|mrj}}: {{W-|mrj|ӹлӹштӓш}} * {{Z|gun}}: {{W-|gun|ogue}} * {{Z|hu}}: {{W+|hu|levél}}, {{W+|hu|falevél}} * {{Z|mel}}: {{W-|mel|daun}} * {{Z|egy}}: {{W-egy|gꜣbt|h=g-A-b-t-Hn:Z2ss}} * {{Z|mvi}}: {{W-|mvi|葉|tr=ぱー, pā}} * {{Z|lus}}: {{W-|lus|hnah}} * {{Z|min}}: {{W-|min|daun}} * {{Z|mwl}}: {{W-|mwl|fuolha|m}} * {{Z|xpq}}: {{W-|xpq|wunipaq}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|навч}} *: Mongolî: {{W-|mn|ᠨᠠᠪᠴᠢ}} * {{Z|mnw}}: {{W-|mnw|သၠ|tr=hlaˀ}} * {{Z|mtq}}: {{W-|mtq|lả}} * {{Z|nah}}: {{W+|nah|izhuatl}} * {{Z|gld}}: {{W-|gld|хабдата}} * {{Z|nv}}: {{W-|nv|atʼąąʼ}} * {{Z|nds}}: *: {{Z|nds-de}}: {{W-|nds-de|Blatt|nt}} * {{Z|ne}}: {{W+|ne|पात}} * {{Z|ncb}}: {{W-|ncb|dai}} * {{Z|nrf}}: {{W-|nrf|fielle|m}}, {{W-|nrf|fieille|m}}, {{W-|nrf|fuule|m}}, {{W-|nrf|fiëly|m}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|blad|nt}}, {{W+|nb|løv|nt}} *: {{Z|nn}}: {{W-|nn|blad|nt}}, {{W-|nn|lauv|nt}} * {{Z|oj}}: {{W-|oj|aniibiishibag}}, {{W-|oj|aniibiishibagoon|p}}, {{W-|oj|aniibiish}}, {{W-|oj|aniibiishan|p}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᐟ|tr=aniibiishibag}}, {{W-|oj|ᐊᓂᐱᐦᔑᐸᑯᐣ|p|tr=aniibiishibagoon}}, {{W-|oj|ᐊᓂᐱᐦᐡ|tr=aniibiish}}, {{W-|oj|ᐊᓂᐱᐦᔕᐣ|p|tr=aniibiishan}} * {{Z|okn}}: {{W-|okn|葉|tr=はー, fā}} * {{Z|ryu}}: {{W-|ryu|葉|tr=ふぁー, fā}} * {{Z|oc}}: {{W+|oc|fuèlha|m}} * {{Z|one}}: {{W-|one|onláhte̲’}} * {{Z|or}}: {{W+|or|ପତ୍ର}} * {{Z|osa}}: {{W-|osa|žąąpé}} * {{Z|os}}: {{W-|os|сыф}} * {{Z|ota}}: {{W-|ota|یپراق|tr=yaprak}} * {{Z|ug}}: {{W-|ug|يوپۇرماق}}, {{W-|ug|ياپراق}} * {{Z|uz}}: {{W+|uz|yaproq}}, {{W+|uz|barg}} * {{Z|pac}}: {{W-|pac|ula}}, {{W-|pac|ila}} * {{Z|pau}}: {{W-|pau|llel}} * Pali: *: {{Z|pi}}: {{W-|pi|ပဏ္ဏ|nt}} *: {{Z|pi}}: {{W-|pi|पण्ण|nt}} *: {{Z|pi}}: {{W-|pi|បណ្ណ|nt}} *: Latînî: {{W-|pi|paṇṇa|nt}} *: {{Z|pi}}: {{W-|pi|පණ්ණ|nt}} *: {{Z|pi}}: {{W-|pi|ปณฺณ|nt}} * {{Z|pap}}: {{W-|pap|foya}} * {{Z|bxd}}: {{W-|bxd|a³¹faʔ⁵⁵}}, {{W-|bxd|sak⁵⁵ faʔ⁵⁵}} * {{Z|ps}}: {{W+|ps|پاڼه|m|tr=pâṇa}} * {{Z|pms}}: {{W-|pms|feuja|m}} * {{Z|ppl}}: {{W-|ppl|iswat}}, {{W-|ppl|izhuat}} * {{Z|pdt}}: {{W-|pdt|Blaut|nt}} * {{Z|pl}}: {{W+|pl|liść|n}} * {{Z|pt}}: {{W+|pt|folha|m}} * {{Z|prn}}: {{W-|prn|pārag}} * {{Z|pa}}: {{W-|pa|ਪੱਤਾ|n}} * {{Z|kk}}: {{W-|kk|жапырақ}} * {{Z|rap}}: {{W-|rap|rua}} * {{Z|rhg}}: {{W-|rhg|fata}} * {{Z|rgn}}: {{W-|rgn|fója|m}} * {{Z|rm}}: {{W-|rm|fegl}} * {{Z|rom}}: {{W-|rom|patrin|m}} * {{Z|ro}}: {{W+|ro|frunză|m}} * {{Z|ru}}: {{W+|ru|лист|n}}, plural for this sense: {{W+|ru|ли́стья|n-p}} * {{Z|ksw}}: {{W-|ksw|သ့ၣ်လၣ်}} * {{Z|ssy}}: {{W-|ssy|dharhaa}} * {{Z|se}}: {{W-|se|lasta}} * {{Z|sm}}: {{W-|sm|lau}} * {{Z|sa}}: {{W+|sa|पर्ण|tr=parṇá|nt}}, {{W+|sa|पत्र|nt}} * {{Z|sc}}: {{W-|sc|fògia|m}} * {{Z|ceb}}: {{W-|ceb|dahon}} * {{Z|sea}}: {{W-|sea|sela}} * {{Z|scn}}: {{W+|scn|fogghia|m}} * {{Z|sd}}: {{W-|sd|پن|n|tr=panu|cuda=پَنُ}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|лист|n}}, {{W-|sh|лиска|m}} *: Latînî: {{W+|sh|list|n}}, {{W+|sh|liska|m}} * {{Z|cu}}: *: Kirîlî: {{W-|cu|листъ|n}} *: Glagolîtîk: {{W-|cu|ⰾⰹⱄⱅⱏ|n}} * {{Z|orv}}: {{W-|orv|листъ|n}} * {{Z|sk}}: {{W+|sk|list|n}} * {{Z|sl}}: {{W+|sl|list|n}} * {{Z|zlw-slv}}: {{W-|zlw-slv|lȧ̃st|n}} * {{Z|so}}: {{W+|so|caleen|m}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|list|n}} *: {{Z|hsb}}: {{W-|hsb|list|n}} * {{Z|es}}: {{W+|es|hoja|m}} * {{Z|su}}: {{W+|su|daun}} * {{Z|sw}}: {{W+|sw|jani|c5|c6}}, {{W+|sw|msahafu|c3|c4}} * {{Z|sv}}: {{W+|sv|blad|nt}}, {{W+|sv|löv|nt}} * {{Z|shn}}: {{W-|shn|မႂ်}}, {{W-|shn|ဝႂ်}} * {{Z|zdj}}: {{W-|zdj|wani|c11|c10}} * {{Z|sn}}: {{W-|sn|shizha}} * {{Z|tg}}: {{W+|tg|барг}} * {{Z|tl}}: {{W+|tl|dahon}} * {{Z|tly}}: {{W-|tly|لیو}} * {{Z|ta}}: {{W+|ta|இலை}} * {{Z|twf}}: {{W-|twf|ə̂na}} * {{Z|roa-tar}}: {{W-|roa-tar|fogghie|m}} * {{Z|rif}}: {{W-|rif|afar|n}}, {{W-|rif|tifrešt|m}} * {{Z|tsg}}: {{W-|tsg|dahun}} * {{Z|th}}: {{W+|th|ใบ}}, {{W+|th|ใบไม้}} * {{Z|te}}: {{W+|te|ఆకు}} * {{Z|tzm}}: {{W-|tzm|ⵉⴼⴻⵔ|n}} * {{Z|tea}}: {{W-|tea|sela}} * {{Z|tt}}: {{W+|tt|яфрак}} * {{Z|tet}}: {{W-|tet|roo}} * {{Z|tr}}: {{W+|tr|yaprak}} * {{Z|tk}}: {{W-|tk|ýaprak}} * {{Z|bo}}: {{W-|bo|ལོ་མ།}} * {{Z|tli}}: {{W-|tli|kayaaní}} * {{Z|tpi}}: {{W-|tpi|lip}} * {{Z|tkn}}: {{W-|tkn|葉|tr=はー, hā}} * {{Z|xto}}: {{W-|xto|pält}} * {{Z|txb}}: {{W-|txb|pilta}} * {{Z|trm}}: {{W-|trm|påṭ}} * {{Z|tcy}}: {{W-|tcy|ಅಡಿಪಿರೆ}} * {{Z|tvl}}: {{W-|tvl|lau}} * {{Z|tpw}}: {{W-|tpw|oba}} * {{Z|udi}}: {{W-|udi|хазал}} * {{Z|udm}}: {{W-|udm|куар}} * {{Z|ur}}: {{W-|ur|پتی|m|tr=patti}} * {{Z|uk}}: {{W+|uk|лист|n}} * {{Z|vec}}: {{W+|vec|foja|m}}, {{W-|vec|fogia|m}} * {{Z|vep}}: {{W-|vep|leht}} * {{Z|vi}}: {{W+|vi|lá}} * {{Z|vo}}: {{W+|vo|bled}} * {{Z|vor}}: {{W-|vor|leht'}} * {{Z|vot}}: {{W-|vot|lehti}} * {{Z|wbk}}: {{W-|wbk|poṭ}} * {{Z|wa}}: {{W+|wa|foye|m}} * {{Z|war}}: {{W-|war|dáhon}} * {{Z|cy}}: {{W+|cy|deilen|m}} * {{Z|wym}}: {{W-|wym|błot|nt}} * {{Z|wo}}: {{W+|wo|xob}} * {{Z|km}}: {{W+|km|ស្លឹក}}, {{W-|km|ស្លឹកឈើ}} * {{Z|xh}}: {{W-|xh|igqabi|c5|c6}} * {{Z|rys}}: {{W-|rys|葉|tr=ぱー, pā}} * {{Z|sah}}: {{W-|sah|сэбирдэх}} * {{Z|yag}}: {{W-|yag|Suka}} * {{Z|yi}}: {{W-|yi|בלאַט|n|m}} * {{Z|yoi}}: {{W-|yoi|葉|tr=はー, hā}} * {{Z|yox}}: {{W-|yox|葉|tr=ぱー, pā}} * {{Z|yo}}: {{W-|yo|ewé}} * {{Z|el}}: {{W+|el|φύλλο|nt}} *: Kevn: {{W-|grc|φύλλον|nt}}, {{W-|grc|πέταλον|nt}} * {{Z|zea}}: {{W-|zea|blad|nt}} * {{Z|za}}: {{W-|za|mbaw}} * {{Z|zu}}: {{W+|zu|ikhasi|c5|c6}}, {{W+|zu|iqabi|c5|c6}} {{werger-bin}} :{{werger çavkanî|en|leaf|beş=Ev qismê Wergerê|oldid=76702326}} {{werger-ser|per, kaxez, weraqe, belgename}} * {{Z|de}}: {{W+|de|Laub}} {{n}}, {{W+|de|Seite}} {{m}}, {{W+|de|Wedel|guman=erê}} {{n}} * {{Z|fa}}: {{W+|fa|برگ}}, {{W+|fa|سند}}, {{W+|fa|صفحه}}, {{W+|fa|برگه|guman=erê}}, {{W-|fa|شراره آتش|guman=erê}}, {{W+|fa|کاغذ|guman=erê}}, {{W+|fa|مدرک|guman=erê}} * {{Z|en}}: {{W+|en|covey}}, {{W+|en|foliage}}, {{W+|en|frond}}, {{W+|en|gleed}}, {{W+|en|platoon}}, {{W+|en|file}}, {{W+|en|phyllo-}} * {{Z|tr}}: {{W+|tr|belge}}, {{W+|tr|çalkantı}}, {{W+|tr|çapak}}, {{W+|tr|lahza|guman=erê}} {{werger-bin}} === Navdêr 2 === [[Wêne:Embers 01.JPG|thumb|250px|pel (2)]] {{navdêr|ku|z=n}} # [[parçe|Parçe]]yên [[agir]]î yên ji [[pirt]]ên [[dar]]î yan [[kumir]]ê yên ku agirî girtine û dişewitin lê hê nebûne [[xwelî]]. #: {{hevmane|ku|pêt}} ==== Bi alfabeyên din ==== * {{ku-ar|په‌ل}} ==== Herwiha ==== * {{g|ku|pêlox}} * {{g|ku|pêreng}} * {{g|ku|piring}} * {{g|ku|piloxt}} ==== Etîmolojî ==== Herwiha [[piring]], [[pêreng]], ji {{ji|ine-pro|ku|*péh₂ur|t=[[agir]]}}. Hevreha çekî [[pýř]] (pel), {{hv|grc|πῦρ}} (pûr: agir > kurdî [[pîroman]]), [[toxarî]] A ''por'' (agir), toxarî B ''puwar'' (agir), hîtîtî ''paḫḫur'' ([[agir]]), danmarkî / norwecî / {{hv|sv|fyr}} (agir), îngilîzî [[fire]] (agir), {{hv|hy|հուր}} (hur: agir)... ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Glut}} {{m}} * {{Z|zh}}: *: [[mandarînî]]: {{W+|cmn|餘燼|sc=Hani|xs=Mandarin}}, {{W+|cmn|余烬|tr=yújìn|sc=Hani|xs=Mandarin}} * {{Z|ar}}: {{W-|ar|جمرة|tr=cemre}} * {{Z|hy}}: {{W-|hy|մարմրող ածուխ|tr=marmroġ açux}} * {{Z|eo}}: {{W-|eo|braĝo|xs=Esperanto}}, {{W-|eo|ardaĵo|xs=Esperanto}} * {{Z|fa}}: {{W+|fa|شعله|sc=fa-Arab}} * {{Z|fi}}: {{W+|fi|kekäle}} * {{Z|fr}}: {{W+|fr|braise}} {{m}} * {{Z|ka}}: {{W-|ka|მღვივარი ნახშირი|tr=mġvivari naxširi}}, {{W-|ka|ცხელი ნაცარი|tr=tsxeli natsari}} * {{Z|nl}}: {{W+|nl|sintel}} * {{Z|io}}: {{W+|io|brezo}} * {{Z|en}}: {{W+|en|embers}}, {{W+|en|ember}}, {{W+|en|bracteole|guman=erê}}, {{W+|en|bractlet|guman=erê}}, {{W+|en|carbuncle|guman=erê}}, {{W+|en|fire-brand|guman=erê}}, {{W+|en|leafage|guman=erê}}, {{W-|en|live coal|guman=erê}}, {{W+|en|phyllome|guman=erê}}, {{W+|en|cigarette paper|guman=erê}} * {{Z|it}}: {{W+|it|brace}} {{m}} * {{Z|ca}}: {{W+|ca|brasa}} {{m}} * {{Z|la}}: {{W+|la|favilla}} {{m}} * {{Z|hu}}: {{W+|hu|zsarátnok}}; [[izzó fa]]([[darab]])/[[széndarab]], {{W+|hu|parázs}} * {{Z|ru}}: {{W+|ru|уголёк|tr=ugoljók}} {{n}}, {{W-|ru|tr=gorjáčaja zolá|горячая зола}} {{m}} * {{Z|sh}}: {{W+|sh|žar}} {{n}}, {{W+|sh|žeravica}} {{m}} * {{Z|es}}: {{W+|es|brasa}} {{m}}, {{W+|es|ascua}} {{m}} * {{Z|th}}: {{W-|th|แสงไฟในเศษฟืน|tr=săeng fai nai sèt feun}}, {{W-|th|ถ่านที่ยังคุอยู่|tr=tàan têe yang kóo yòo}}, {{W-|th|เถ้าที่ยังคุกกรุ่นอยู่|tr=tâo têe yang kóok gròon yòo}} * {{Z|tr}}: {{W+|tr|kor}}, {{W+|tr|köz}}, {{W+|tr|levha|guman=erê}}, {{W+|tr|manga|guman=erê}}, {{W+|tr|sarma|guman=erê}}, {{W+|tr|takım|guman=erê}}, {{W+|tr|talaş|guman=erê}}, {{W+|tr|talaz|guman=erê}}, {{W+|tr|tim|guman=erê}}, {{W+|tr|titrek kavak|guman=erê}}, {{W+|tr|varak|guman=erê}} {{werger-bin}} === Navdêr 3 === {{navdêr|ku|z=?}} # [[kelûpel]], [[tişt]], [[hûrûmûr]] ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|item}}, {{W+|en|goods}}, {{W+|en|wares}}, {{W+|en|products}} {{werger-bin}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza}} # [[pel]] == {{ziman|gl}} == === Navdêr === {{navdêr|gl|z=m}} # {{f|gl|anatomî}} [[çerm#ku|çerm]] == {{ziman|oc}} == === Navdêr === {{navdêr|oc|z=n}} # {{f|oc|anatomî}} [[mû#ku|mû]], [[pûrt#ku|pûrt]], [[pirç#ku|pirç]] == {{ziman|rm}} == === Navdêr === {{navdêr|rm}} # {{f|rm|anatomî}} [[çerm#ku|çerm]] ptu7nb659ppcc5ezu1sdhveo1op59te ava 0 3656 6241668 6101806 2026-07-11T20:37:21Z Wikihez 7344 6241668 wikitext text/x-wiki {{bnr-h|Ava}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{beş|Rengdêr}} {{deng|ku|LL-Q36163 (kmr)-Key Mîrza-ava.wav|Deng|Wan}} * {{beş|Formeke navdêrê}} {{deng|ku|LL-Q36163 (kmr)-Key Mîrza-ava-2.wav|Deng|Wan}} * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|ava}} {{rengdêr|ku}} # Ne [[kavil]], ne [[xirabe]], ne [[xirabkirî]], ne [[xopan]], ne [[wêran]], ne [[ruxandî]], ne [[hilweşandî]] #: {{hevmaneyên peyvê|ku|çêkirî|dirist|birêk|birêkûpêk|lidar|çalak|liserxwe}} #: {{dijmane|ku|kavil|wêran|xirabe|xopan}} #* {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Spêde kifş-i bû dîsa</br>Merîxa nehsê '''ava''' bû</br>Xwiya bû roj di şerqê da}} ==== Bi alfabeyên din ==== * {{ku-ar|ئاڤا}} ==== Herwiha ==== * {{g|ku|awa}} (2) ==== Jê ==== {{kol3|ku|cure=Jê |-ava |avahî |avakar |avakarî |avaker |avakerî |avanî |avatî |avayî |ava kirin<q:lêker> |ava bûn<q:lêker> |avabûn<q:navdêr> |avakirin<q:navdêr> |avadan |avabûyî<q:rengdêr> |avakirî<q:rengdêr> |avaçûyî }} ==== Etîmolojî ==== Ji {{mîr|ira-pro|ku|*āpāta-}} ji {{ji|ine-pro|ku|*peh₂-|w=[[parastin]]}}, têkilî {{hv|fa|آباد|tr=abad}} û {{hv|ckb|ئاوه‌دان}} / [[awedan]], {{hv|zza|awan}}. Belkî hevreha {{hv|sa|आवास}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|built}} * {{Z|tr}}: {{W+|tr|bayındır}}, {{W+|tr|mamur}}, {{W+|tr|şen}}, {{W+|tr|abat}} {{werger-bin}} === Formeke navdêrê === {{ku-tew-nav|av|mê|îzafe|binavkirî}} {{navdêr|ku|form=erê}} # {{formeke peyvê|ku|av||îzafe|yekjimar|binavkirî}} ajo78av5vtpzq8fa6v87n0hrhphznwg lingwistîk 0 5080 6241712 5890695 2026-07-11T23:57:19Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241712 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{navdêr|ku|z=-}} # {{guharto|ku|lenguîstîk}} #* {{bêmînak|ku}} 0643cauoih4dra2krs0trqw7dy12obo kursî 0 6008 6241720 6129691 2026-07-12T00:26:58Z Wikihez 7344 /* Navdêr */ 6241720 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|kursî|mê}} [[Wêne:Chair.png|thumb|kursiyek]] {{navdêr|ku|z=m}}, {{k-ya nerm}}, {{r-ya nerm}} # {{f|ku|mobîlya}} Alavên bi[[pişt]] û bi[[pêpik]] yên bi [[giştî]] bo [[rûniştin]]a kesekî. #: {{mk|ku|Rûne ser '''kursiyê'''.}} #: {{mk|ku|Li ser '''kursiyê''' rûniştim.}} #: {{mk|ku|Ji ser '''kursiyê''' rabû.}} #: {{mk|ku|Hemû '''kursî''' girtî bûn.|Li ser her yekê kesek hebû û ti yên vala tine bûn.|rêz=1}} # [[diran|Diran]]ên [[paşîn]]. #* {{bêmînak|ku}} # [[meqam|Meqam]], [[cih]]. #* {{bêmînak|ku}} # [[meqam|Meqam]]ê [[paşa]]yan/[[desthilatdar]]an. #: {{hevmane|ku|text}} #: {{mk|ku|text û '''kursî'''}} # [[meqam|Meqam]]ê [[Xwedê]]. #: {{hevmane|ku|erş}} #: {{mk|ku|Ayeta '''Kursî'''|[[ayet]]a 2:255 a [[Qur'an]]ê ye û behsa bê[[hevta]]yiya [[Xwedê]] dike}} #* {{jêder|ku|jêgirtin="Nîveka dî çêkirin ji çarî çîz</br>'Erş û '''kursî''' û qelem lewhe temîz</br>Hate emrê Padîşahê [[Layezal]]"'' |Mela Hisênê Bateyî: ''Mewlûd''}} # Îdareya di nav [[unîversîte]]yan de ku li ser meseleyeke diyarkirî lêkolîn û dersan dide. #: {{nm|ku|'''Kursiya''' zimanê kurdî di sala 1945an de ji aliyê Roger Lescot (1914-1975) ve hate avakirin.}} ==== Bi alfabeyên din ==== * {{ku-ar|کورسی}} * {{ku-kr|курси}} ==== Herwiha ==== * {{g|ku|kursîk}} ==== Hevmane ==== * {{g|ku|sendelî}} * {{g|ku|sendelye}} * {{g|ku|rûniştek}} ==== Binêre herwiha ==== {{kol3|ku |balguh |balîf |doşek |doşk |lihêf |mobîlya |nivîn |palpişt |qaîdok |qenepe |rûniştek |sofa |text }} ==== Jê ==== * {{g|ku|rûniştin}} ser kursiyê * li ser kursiyê [[rûniştin]] * ji ser kursiyê [[rabûn]] * {{g|ku|kursîk}} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|کورسی}}, zazakî {{q|zza|kursî}}, {{hv|fa|کورسی|tr=berê "kursî", niha "korsî"}}, tirkî {{q|tr|kürsü}} (bi tirkiya osmanî {{g|ota|كرسى|ts=kursî}}), erebî {{g|ar|‏كرسي}} (bi erebiya standard "kursiyy", bi erebiya devkî "kursî, kirsî"), siryanî {{g|syc|ܟܘܪܣܝܐ‎|tr=kursiya}}, [[aramî]] {{g|arc|כרסא|tr=kursa}} û {{g|arc|כסא|tr=kusa}}, îbranî {{ge|he|כיסא|tr=kissê}}, ugarîtî [[𐎋𐎒𐎜]] (kisủ), akadî [[𒄖𒍝]] / [[𒄑𒄖𒍝]] (kussû, kursû)... hemû ji {{ji|sux|ku|𒄖𒍝|tr=gu.za}}. Peyv ji Rojhilata Navîn belav bûye Başûrê Asyayê jî: ûrdûyî {{g|ur|کرسی|tr=kursī}}, peştûyî {{g|ps|کورسۍ‎|tr=kursiy}}, hindî [[कुरसी]] (kursī), punjabî [[ਕੁਰਸੀ]] (kursī)... ;{{biçûk|Çavkanî: * {{kitêb|sernavê orjînalThe Pennsylvania Sumerian Dictionary|sernav=Ferhenga sûmerî ya Pennsylvaniayê|url=http://psd.museum.upenn.edu/nepsd-frame.html}} * {{kitêb|url=http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=16&language=id|sernav=Rêkxistina Aşûrîdostan ya Fransayê: Ferhenga akadî|sernavê orjînal='Association Assyrophile de France: Dictionnaire akkadien}} }} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|stoel}} * {{Z|sq}}: {{W-|sq|karrike|m}}, {{W+|sq|karrige}} * {{Z|de}}: {{W+|de|Stuhl|n}} * {{Z|ast}}: {{W+|ast|siella}} * {{Z|az}}: {{W+|az|stul}} * {{Z|eu}}: {{W+|eu|aulki}} * {{Z|bar}}: {{W--|bar|Sessl|n}} * {{Z|be}}: {{W-|be|стул|tr=stul}} * {{Z|br}}: {{W+|br|kador|m}} * {{Z|bg}}: {{W+|bg|стол|tr=stol}} * {{Z|cs}}: {{W+|cs|židle}} * {{Z|zh}}: {{W+|zh|椅子|tr=yǐzi}} * {{Z|da}}: {{W+|da|stol}} * {{Z|id}}: {{W+|id|kursi}} * {{Z|ary}}: {{W--|ary|كرسي}}, {{W--|ary|شلية}} *: {{Z|arz}}: {{W|arz|كرسي|tr=kursî}} {{n}} * {{Z|ar}}: {{W|ar|كرسي|tr=kursiyy}} {{n}}, {{W|ar|مقعد|tr=meq'ed}} {{n}} * {{Z|hy}}: {{W+|hy|աթոռ|tr=atʿoṙ}} * {{Z|eo}}: {{W+|eo|seĝo}} * {{Z|et}}: {{W+|et|tool}} * {{Z|ewo}}: {{W--|ewo|etoa}} * {{Z|fa}}: {{W+|fa|صندلی|tr=sendelî}}, {{W|fa|کرسی|tr=korsî}} * {{Z|fo}}: {{W-|fo|stólur}} * {{Z|fi}}: {{W+|fi|tuoli}}, {{W|fi|istuin}} * {{Z|frp}}: ''(savoyard)'' {{W--|frp|sala}} * {{Z|fr}}: {{W|fr|chaise}} * {{Z|fy}}: {{W-|fy|stoel}}, {{W-|fy|belech}} * {{Z|gd}}: {{W-|gd|suidheachan}}, {{W-|gd|cathair}} * {{Z|gl}}: {{W+|gl|cadeira|m}} * {{Z|ka}}: {{W+|ka|სკამი|tr=sḳami}} * {{Z|hi}}: {{W+|hi|कुरसी|tr=kursī}} * {{Z|nl}}: {{W+|nl|stoel}}, {{W+|nl|zetel}} * {{Z|he}}: {{W+|he|כיסא|tr=kisé}} * {{Z|io}}: {{W+|io|stulo}} * {{Z|ang}}: {{W-|ang|stol}} * {{Z|en}}: {{W+|en|chair}}, {{W+|en|seat}} * {{Z|ga}}: {{W+|ga|cathaoir}} * {{Z|it}}: {{W+|it|assedio}}, {{W+|it|sedia}}, {{W+|it|seggiola}} * {{Z|is}}: {{W+|is|stóll}} * {{Z|ja}}: {{W+|ja|椅子|tr=isu}}, {{W+|ja|いす|tr=isu}} * {{Z|ca}}: {{W+|ca|cadira}} * {{Z|ki}}: {{W--|ki|giti}} * {{Z|ko}}: {{W+|ko|의자|tr=uija}} * {{Z|kw}}: {{W-|kw|cadar}} * {{Z|co}}: {{W+|co|sedia}}, {{W-|co|carreca}} * {{Z|mfe}}: {{W--|mfe|sez}} * {{Z|la}}: {{W-|la|sella}}, {{W-|la|cathedra}}, {{W-|la|solium}} * {{Z|lv}}: {{W+|lv|krēsls}} * {{Z|lo}}: {{W+|lo|ຕັ່ງ}} * {{Z|lt}}: {{W+|lt|kėdė}} * {{Z|mk}}: {{W-|mk|стол|tr=stol}}, {{W-|mk|столица|tr=stolica}} * {{Z|mg}}: {{W+|mg|seza}} * {{Z|ms}}: {{W+|ms|kursi}} * {{Z|mt}}: {{W+|mt|siġġu}} * {{Z|gv}}: {{W-|gv|caair}} * {{Z|yua}}: {{W--|yua|k’anche’}} * {{Z|hu}}: {{W+|hu|szék}} * {{Z|mn}}: {{W+|mn|сандал|tr=sandal}} * {{Z|nrf}}: {{W--|nrf|caire}} * {{Z|no}}: {{W+|no|stol|nt}} * {{Z|oc}}: {{W+|oc|cadièra|m}} * {{Z|uz}}: {{W+|uz|o`rindiq}} * {{Z|uz}}: {{W|uz|o`rindiq}} * {{Z|pap}}: {{W--|pap|stul}} * {{Z|pl}}: {{W+|pl|krzesło}} * {{Z|pt}}: {{W+|pt|cadeira|m}}, {{W+|pt|assento}} * {{Z|kk}}: {{W+|kk|орындық|tr=orındıq}}, {{W-|kk|отырғыш|tr=otırğış}} * {{Z|ro}}: {{W+|ro|scaun}} * {{Z|ru}}: {{W+|ru|стул}} * {{Z|se}}: {{W--|se|stuollu}} * {{Z|srn}}: {{W--|srn|sturu}} * {{Z|sh}}: :* Latînî: {{W+|sh|stolac}}, {{W+|sh|stolica}} :* Kirîlî: {{W-|sh|столац}}, {{W+|sh|столица}} * {{Z|sk}}: {{W-|sk|stolička}} * {{Z|sl}}: {{W+|sl|stol}} * {{Z|dsb}}: {{W--|dsb|stoł}} * {{Z|hsb}}: {{W-|hsb|stólc}} * {{Z|es}}: {{W+|es|silla|m}} * {{Z|sw}}: {{W+|sw|kiti}} * {{Z|sv}}: {{W+|sv|stol}} * {{Z|shy}}: {{W--|shy|amɣim}} * {{Z|zdj}}: {{W--|zdj|hiri}} * {{Z|tg}}: {{W-|tg|сандали|tr=sandali}}, {{W+|tg|курсӣ|tr=kursī}} * {{Z|tl}}: {{W-|tl|sílya}}, {{W-|tl|úpuan}} * {{Z|ta}}: {{W+|ta|நாற்காலி|tr=nāṟkāli}} * {{Z|th}}: {{W+|th|เก้าอี้|tr=gâo-îi}} * {{Z|tr}}: {{W+|tr|sandalye}}, {{W|tr|sandalye}}, {{W|tr|kürsü}}, {{W|tr|koltuk}}, {{W|tr|iskemle}}, {{W|tr|oturak}}, {{W|tr|tabure}}, {{W|tr|sekmen}} * {{Z|tk}}: {{W-|tk|oturgyç}} * {{Z|ur}}: {{W-|ur|کرسی|tr=kursī}} * {{Z|ur}}: {{W|ur|کرسی|tr=kursī}} {{n}} * {{Z|uk}}: {{W+|uk|стілець|tr=stilécʹ}}, {{W-|uk|крісло|tr=kríslo}} * {{Z|vec}}: {{W|vec|carega}} * {{Z|vi}}: {{W|vi|ghế}} * {{Z|cy}}: {{W+|cy|cadair}} * {{Z|cy}}: {{W|cy|cadair}}, {{W|cy|ystôl}} * {{Z|km}}: {{W+|km|កៅអី|tr=kav ’əy}} * {{Z|yi}}: {{W|yi|שטול}} * {{Z|el}}: {{W+|el|καρέκλα|tr=karékla}} * {{Z|el}}: {{W|el|καρέκλα}} {{n}} (karékla) * {{Z|zu}}: {{W+|zu|isihlalo}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # {{ckb-Arab|کورسی}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza}} # [[kursî#Kurmancî|kursî]] #* {{bêmînak|zza}} 13vzbzeoq0dyh5kds93ggr28xpqceji 6241721 6241720 2026-07-12T00:27:28Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241721 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|kursî|mê}} [[Wêne:Chair.png|thumb|kursiyek]] {{navdêr|ku|z=m}}, {{k-ya nerm}}, {{r-ya nerm}} # {{f|ku|mobîlya}} Alavên bi[[pişt]] û bi[[pêpik]] yên bi [[giştî]] bo [[rûniştin]]a kesekî. #: {{mk|ku|Rûne ser '''kursiyê'''.}} #: {{mk|ku|Li ser '''kursiyê''' rûniştim.}} #: {{mk|ku|Ji ser '''kursiyê''' rabû.}} #: {{mk|ku|Hemû '''kursî''' girtî bûn.|Li ser her yekê kesek hebû û ti yên vala tine bûn.|rêz=1}} # [[diran|Diran]]ên [[paşîn]]. #* {{bêmînak|ku}} # [[meqam|Meqam]], [[cih]]. #* {{bêmînak|ku}} # [[meqam|Meqam]]ê [[paşa]]yan/[[desthilatdar]]an. #: {{hevmane|ku|text}} #: {{mk|ku|text û '''kursî'''}} # [[meqam|Meqam]]ê [[Xwedê]]. #: {{hevmane|ku|erş}} #: {{mk|ku|Ayeta '''Kursî'''|[[ayet]]a 2:255 a [[Qur'an]]ê ye û behsa bê[[hevta]]yiya [[Xwedê]] dike}} #* {{jêder|ku|jêgirtin="Nîveka dî çêkirin ji çarî çîz</br>'Erş û '''kursî''' û qelem lewhe temîz</br>Hate emrê Padîşahê [[Layezal]]"'' |Mela Hisênê Bateyî: ''Mewlûd''}} # {{e|ku|tehsîl}} Îdareya di nav [[unîversîte]]yan de ku li ser meseleyeke diyarkirî lêkolîn û dersan dide. #: {{nm|ku|'''Kursiya''' zimanê kurdî di sala 1945an de ji aliyê Roger Lescot (1914-1975) ve hate avakirin.}} ==== Bi alfabeyên din ==== * {{ku-ar|کورسی}} * {{ku-kr|курси}} ==== Herwiha ==== * {{g|ku|kursîk}} ==== Hevmane ==== * {{g|ku|sendelî}} * {{g|ku|sendelye}} * {{g|ku|rûniştek}} ==== Binêre herwiha ==== {{kol3|ku |balguh |balîf |doşek |doşk |lihêf |mobîlya |nivîn |palpişt |qaîdok |qenepe |rûniştek |sofa |text }} ==== Jê ==== * {{g|ku|rûniştin}} ser kursiyê * li ser kursiyê [[rûniştin]] * ji ser kursiyê [[rabûn]] * {{g|ku|kursîk}} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|کورسی}}, zazakî {{q|zza|kursî}}, {{hv|fa|کورسی|tr=berê "kursî", niha "korsî"}}, tirkî {{q|tr|kürsü}} (bi tirkiya osmanî {{g|ota|كرسى|ts=kursî}}), erebî {{g|ar|‏كرسي}} (bi erebiya standard "kursiyy", bi erebiya devkî "kursî, kirsî"), siryanî {{g|syc|ܟܘܪܣܝܐ‎|tr=kursiya}}, [[aramî]] {{g|arc|כרסא|tr=kursa}} û {{g|arc|כסא|tr=kusa}}, îbranî {{ge|he|כיסא|tr=kissê}}, ugarîtî [[𐎋𐎒𐎜]] (kisủ), akadî [[𒄖𒍝]] / [[𒄑𒄖𒍝]] (kussû, kursû)... hemû ji {{ji|sux|ku|𒄖𒍝|tr=gu.za}}. Peyv ji Rojhilata Navîn belav bûye Başûrê Asyayê jî: ûrdûyî {{g|ur|کرسی|tr=kursī}}, peştûyî {{g|ps|کورسۍ‎|tr=kursiy}}, hindî [[कुरसी]] (kursī), punjabî [[ਕੁਰਸੀ]] (kursī)... ;{{biçûk|Çavkanî: * {{kitêb|sernavê orjînalThe Pennsylvania Sumerian Dictionary|sernav=Ferhenga sûmerî ya Pennsylvaniayê|url=http://psd.museum.upenn.edu/nepsd-frame.html}} * {{kitêb|url=http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=16&language=id|sernav=Rêkxistina Aşûrîdostan ya Fransayê: Ferhenga akadî|sernavê orjînal='Association Assyrophile de France: Dictionnaire akkadien}} }} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|stoel}} * {{Z|sq}}: {{W-|sq|karrike|m}}, {{W+|sq|karrige}} * {{Z|de}}: {{W+|de|Stuhl|n}} * {{Z|ast}}: {{W+|ast|siella}} * {{Z|az}}: {{W+|az|stul}} * {{Z|eu}}: {{W+|eu|aulki}} * {{Z|bar}}: {{W--|bar|Sessl|n}} * {{Z|be}}: {{W-|be|стул|tr=stul}} * {{Z|br}}: {{W+|br|kador|m}} * {{Z|bg}}: {{W+|bg|стол|tr=stol}} * {{Z|cs}}: {{W+|cs|židle}} * {{Z|zh}}: {{W+|zh|椅子|tr=yǐzi}} * {{Z|da}}: {{W+|da|stol}} * {{Z|id}}: {{W+|id|kursi}} * {{Z|ary}}: {{W--|ary|كرسي}}, {{W--|ary|شلية}} *: {{Z|arz}}: {{W|arz|كرسي|tr=kursî}} {{n}} * {{Z|ar}}: {{W|ar|كرسي|tr=kursiyy}} {{n}}, {{W|ar|مقعد|tr=meq'ed}} {{n}} * {{Z|hy}}: {{W+|hy|աթոռ|tr=atʿoṙ}} * {{Z|eo}}: {{W+|eo|seĝo}} * {{Z|et}}: {{W+|et|tool}} * {{Z|ewo}}: {{W--|ewo|etoa}} * {{Z|fa}}: {{W+|fa|صندلی|tr=sendelî}}, {{W|fa|کرسی|tr=korsî}} * {{Z|fo}}: {{W-|fo|stólur}} * {{Z|fi}}: {{W+|fi|tuoli}}, {{W|fi|istuin}} * {{Z|frp}}: ''(savoyard)'' {{W--|frp|sala}} * {{Z|fr}}: {{W|fr|chaise}} * {{Z|fy}}: {{W-|fy|stoel}}, {{W-|fy|belech}} * {{Z|gd}}: {{W-|gd|suidheachan}}, {{W-|gd|cathair}} * {{Z|gl}}: {{W+|gl|cadeira|m}} * {{Z|ka}}: {{W+|ka|სკამი|tr=sḳami}} * {{Z|hi}}: {{W+|hi|कुरसी|tr=kursī}} * {{Z|nl}}: {{W+|nl|stoel}}, {{W+|nl|zetel}} * {{Z|he}}: {{W+|he|כיסא|tr=kisé}} * {{Z|io}}: {{W+|io|stulo}} * {{Z|ang}}: {{W-|ang|stol}} * {{Z|en}}: {{W+|en|chair}}, {{W+|en|seat}} * {{Z|ga}}: {{W+|ga|cathaoir}} * {{Z|it}}: {{W+|it|assedio}}, {{W+|it|sedia}}, {{W+|it|seggiola}} * {{Z|is}}: {{W+|is|stóll}} * {{Z|ja}}: {{W+|ja|椅子|tr=isu}}, {{W+|ja|いす|tr=isu}} * {{Z|ca}}: {{W+|ca|cadira}} * {{Z|ki}}: {{W--|ki|giti}} * {{Z|ko}}: {{W+|ko|의자|tr=uija}} * {{Z|kw}}: {{W-|kw|cadar}} * {{Z|co}}: {{W+|co|sedia}}, {{W-|co|carreca}} * {{Z|mfe}}: {{W--|mfe|sez}} * {{Z|la}}: {{W-|la|sella}}, {{W-|la|cathedra}}, {{W-|la|solium}} * {{Z|lv}}: {{W+|lv|krēsls}} * {{Z|lo}}: {{W+|lo|ຕັ່ງ}} * {{Z|lt}}: {{W+|lt|kėdė}} * {{Z|mk}}: {{W-|mk|стол|tr=stol}}, {{W-|mk|столица|tr=stolica}} * {{Z|mg}}: {{W+|mg|seza}} * {{Z|ms}}: {{W+|ms|kursi}} * {{Z|mt}}: {{W+|mt|siġġu}} * {{Z|gv}}: {{W-|gv|caair}} * {{Z|yua}}: {{W--|yua|k’anche’}} * {{Z|hu}}: {{W+|hu|szék}} * {{Z|mn}}: {{W+|mn|сандал|tr=sandal}} * {{Z|nrf}}: {{W--|nrf|caire}} * {{Z|no}}: {{W+|no|stol|nt}} * {{Z|oc}}: {{W+|oc|cadièra|m}} * {{Z|uz}}: {{W+|uz|o`rindiq}} * {{Z|uz}}: {{W|uz|o`rindiq}} * {{Z|pap}}: {{W--|pap|stul}} * {{Z|pl}}: {{W+|pl|krzesło}} * {{Z|pt}}: {{W+|pt|cadeira|m}}, {{W+|pt|assento}} * {{Z|kk}}: {{W+|kk|орындық|tr=orındıq}}, {{W-|kk|отырғыш|tr=otırğış}} * {{Z|ro}}: {{W+|ro|scaun}} * {{Z|ru}}: {{W+|ru|стул}} * {{Z|se}}: {{W--|se|stuollu}} * {{Z|srn}}: {{W--|srn|sturu}} * {{Z|sh}}: :* Latînî: {{W+|sh|stolac}}, {{W+|sh|stolica}} :* Kirîlî: {{W-|sh|столац}}, {{W+|sh|столица}} * {{Z|sk}}: {{W-|sk|stolička}} * {{Z|sl}}: {{W+|sl|stol}} * {{Z|dsb}}: {{W--|dsb|stoł}} * {{Z|hsb}}: {{W-|hsb|stólc}} * {{Z|es}}: {{W+|es|silla|m}} * {{Z|sw}}: {{W+|sw|kiti}} * {{Z|sv}}: {{W+|sv|stol}} * {{Z|shy}}: {{W--|shy|amɣim}} * {{Z|zdj}}: {{W--|zdj|hiri}} * {{Z|tg}}: {{W-|tg|сандали|tr=sandali}}, {{W+|tg|курсӣ|tr=kursī}} * {{Z|tl}}: {{W-|tl|sílya}}, {{W-|tl|úpuan}} * {{Z|ta}}: {{W+|ta|நாற்காலி|tr=nāṟkāli}} * {{Z|th}}: {{W+|th|เก้าอี้|tr=gâo-îi}} * {{Z|tr}}: {{W+|tr|sandalye}}, {{W|tr|sandalye}}, {{W|tr|kürsü}}, {{W|tr|koltuk}}, {{W|tr|iskemle}}, {{W|tr|oturak}}, {{W|tr|tabure}}, {{W|tr|sekmen}} * {{Z|tk}}: {{W-|tk|oturgyç}} * {{Z|ur}}: {{W-|ur|کرسی|tr=kursī}} * {{Z|ur}}: {{W|ur|کرسی|tr=kursī}} {{n}} * {{Z|uk}}: {{W+|uk|стілець|tr=stilécʹ}}, {{W-|uk|крісло|tr=kríslo}} * {{Z|vec}}: {{W|vec|carega}} * {{Z|vi}}: {{W|vi|ghế}} * {{Z|cy}}: {{W+|cy|cadair}} * {{Z|cy}}: {{W|cy|cadair}}, {{W|cy|ystôl}} * {{Z|km}}: {{W+|km|កៅអី|tr=kav ’əy}} * {{Z|yi}}: {{W|yi|שטול}} * {{Z|el}}: {{W+|el|καρέκλα|tr=karékla}} * {{Z|el}}: {{W|el|καρέκλα}} {{n}} (karékla) * {{Z|zu}}: {{W+|zu|isihlalo}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # {{ckb-Arab|کورسی}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza}} # [[kursî#Kurmancî|kursî]] #* {{bêmînak|zza}} 2j2mrf0fvazg0zjofoyddl4v1z8xdre şofêr 0 21051 6241704 6229915 2026-07-11T23:42:29Z Wikihez 7344 /* Herwiha */ 6241704 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|şofêr|mê û nêr}} [[Wêne:Driver_Dave_Marshall_The_Friendly_Bus_Driver.jpg|thumb|'''Şofêrê''' [[otobûs]]an.]] {{navdêr|ku|z=mn}} # {{e|ku|meslek}} Kesê ku tiştekî [[ajotin|diajo]] (xisûsen [[erebe]]yekê). #: {{hevmaneyên peyvê|ku|ajovan|ajokar|sayêq}} #: {{nm|ku|Ew '''şofêrê''' taksiyê ye.}} ==== Bi alfabeyên din ==== * {{ku-ar|شۆفێر}} ==== Herwiha ==== * {{g|ku|şofer}} * {{g|ku|şoferr}} * {{g|ku|şofêrr}} * {{g|ku|şifêr}} ==== Jê ==== * {{g|ku|şofêrî}} * {{g|ku|şofêrîtî}} * {{g|ku|şofêrtî}} ==== Etîmolojî ==== Ji {{deyn|fr|ku|chauffeur}}. ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|shofer|n}}, {{W-|sq|makinist|n}} * {{Z|de}}: {{W+|de|Fahrer|n}}, {{W+|de|Fahrerin|m}} * {{Z|az}}: {{W+|az|sürücü}}, {{W-|az|şofer}}, {{W-|az|ranəndə}} * {{Z|be}}: {{W-|be|кіро́ўца|n}}, {{W-|be|вадзі́цель|n}}, {{W-|be|шафёр|n}} * {{Z|bcl}}: {{W-|bcl|drayber}} * {{Z|bg}}: {{W+|bg|шофьо́р|n}} * {{Z|my}}: {{W+|my|ယာဉ်မောင်း}} * {{Z|cs}}: {{W+|cs|řidič|n}}, {{W+|cs|řidička|m}}, {{W+|cs|šofér|n}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|司機}}, {{W-|yue|駕駛員}}, {{W-|yue|駕駛者}}, {{W-|yue|柴可夫}} *: {{Z|cmn}}: {{W+|cmn|司機}}, {{W+|cmn|駕駛員}}, {{W-|cmn|駕駛者}} * {{Z|da}}: {{W+|da|chauffør|g}} * {{Z|id}}: {{W+|id|sopir}} * {{Z|ar}}: {{W+|ar|سائق|cuda=سَائِق|n}}, {{W-|ar|سَوَّاق|n}} *: {{Z|arz}}: {{W-|arz|سواق|n|tr=sawwāʔ}} *: {{Z|acw}}: {{W-|acw|سَوَّاق|n|tr=sawwāg}} * {{Z|hy}}: {{W+|hy|վարորդ}} * {{Z|eo}}: {{W-|eo|aŭtomobilisto}}, {{W-|eo|aŭtisto}} * {{Z|et}}: {{W+|et|juht}}, {{W-|et|autojuht}} * {{Z|fa}}: {{W+|fa|راننده|tr=rânande}}, {{W+|fa|شوفر|tr=šôfer}}, {{W-|fa|موترران|tr=motarrân}} * {{Z|fo}}: {{W-|fo|bilførari|n}}, {{W-|fo|bussførari|n}}, {{W-|fo|motorsúkklistur|n}}, {{W-|fo|lastbilførari|n}} * {{Z|fi}}: {{W+|fi|kuljettaja}}, {{W+|fi|ajaja}}, {{W+|fi|kuski}} * {{Z|fr}}: {{W+|fr|conducteur|n}}, {{W+|fr|conductrice|m}}, {{W+|fr|chauffeur|n}}, {{W+|fr|chauffeuse|m}} * {{Z|ka}}: {{W-|ka|მძღოლი}} * {{Z|hi}}: {{W+|hi|चालक|n}}, {{W+|hi|ड्राइवर|n}} * {{Z|nl}}: {{W+|nl|bestuurder|n}}, {{W+|nl|chauffeur|n}} * {{Z|he}}: {{W+|he|נַהָג|n|tr=nahág}}, {{W+|he|נֶהָג|n|tr=nehág}}, {{W-|he|נהגת|m|tr=naheget}} * {{Z|en}}: {{W+|en|driver}} * {{Z|ga}}: {{W-|ga|tiománaí|n}} * {{Z|it}}: {{W+|it|autista|n|m}}, {{W+|it|guidatore|n}}, {{W-|it|guidatrice|m}} * {{Z|is}}: {{W-|is|ökumaður|n}}, {{W-|is|bílstjóri|n}} * {{Z|ja}}: {{W+|ja|運転手|tr=うんてんしゅ, untenshu}}, {{W+|ja|運転者|tr=うんてんしゃ, untensha}}, {{W+|ja|ドライバ|tr=doraiba}}, {{W+|ja|ドライバー|tr=doraibā}} * {{Z|kl}}: {{W-|kl|biilertoq}} * {{Z|ca}}: {{W+|ca|conductor|n}}, {{W+|ca|xofer|n}}, {{W+|ca|xòfer|n}} * {{Z|ky}}: {{W-|ky|жүргүзүүчү}}, {{W+|ky|айдоочу}}, {{W+|ky|шофёр}} * {{Z|swb}}: {{W-|swb|shofera|c5|c6}} * {{Z|ko}}: {{W+|ko|운전사}}, {{W+|ko|운전자}}, {{W+|ko|기사}}, {{W+|ko|운전기사}}, {{W+|ko|드라이버}} * {{Z|la}}: {{W-|la|auriga|n}} * {{Z|lv}}: {{W+|lv|vadītājs|n}}, {{W-|lv|šoferis|n}} * {{Z|lo}}: {{W-|lo|ຄົນຂັບລົດ}} * {{Z|lt}}: {{W-|lt|vairuotojas|n}}, {{W-|lt|šoferis|n}} * {{Z|mk}}: {{W-|mk|возач|n}}, {{W-|mk|шофер|n}} * {{Z|ms}}: {{W+|ms|pemandu}}, {{W-|ms|drebar}} * {{Z|mt}}: {{W-|mt|sewwieq|n}}, {{W-|mt|sewwieqa|m}}, {{W-|mt|xufier|n}}, {{W-|mt|xufiera|m}} * {{Z|mi}}: {{W-|mi|kaitaraiwa}} * {{Z|mr}}: {{W-|mr|चालक|n}}, {{W-|mr|चालिका|m}} * {{Z|hu}}: {{W+|hu|sofőr}}, {{W+|hu|vezető}}, {{W+|hu|járművezető}}, {{W+|hu|gépjárművezető}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|жолооч}} * {{Z|nrf}}: {{W-|nrf|cacheux|n}} * {{Z|no}}: *: {{Z|nb}}: {{W-|nb|fører|n}}, {{W+|nb|sjåfør|n}} *: {{Z|nn}}: {{W-|nn|førar|n}}, {{W-|nn|sjåfør|n}} * {{Z|ug}}: {{W-|ug|شوپۇر}} * {{Z|uz}}: {{W+|uz|haydovchi}}, {{W+|uz|shofyor}} * {{Z|ps}}: {{W-|ps|ډرايور|n|tr=ḍrāywar}}, {{W-|ps|ډرېور|n|tr=ḍrewar}}, {{W-|ps|موټروان|n|tr=moṭarwān}} * {{Z|pl}}: {{W+|pl|kierowca|n}}, {{W+|pl|szofer|n}}, {{W+|pl|automobilista|n}}, {{W-|pl|automobilistka|m}} * {{Z|pt}}: {{W+|pt|motorista|n|m}}, {{W+|pt|condutor|n}}, {{W+|pt|condutora|m}} * {{Z|kk}}: {{W+|kk|жүргізуші}}, {{W-|kk|шопыр}} * {{Z|ro}}: {{W+|ro|șofer|n}}, {{W-|ro|conducător auto|n}} * {{Z|ru}}: {{W+|ru|води́тель|n}}, {{W+|ru|води́тельница|m}}, {{W+|ru|шофёр|n}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|во̀за̄ч|n}}, {{W-|sh|воза̀чица|m}} *: Latînî: {{W+|sh|vòzāč|n}}, {{W+|sh|vozàčica|m}} * {{Z|sk}}: {{W-|sk|vodič|n}}, {{W-|sk|šofér|n}} * {{Z|sl}}: {{W+|sl|voznik|n}}, {{W-|sl|šofer|n}} * {{Z|es}}: {{W+|es|conductor|n}}, {{W-|es|conductora|m}}, {{W+|es|chofer|n}} * {{Z|sw}}: {{W+|sw|dereva}} * {{Z|sv}}: {{W+|sv|förare|g}}, {{W+|sv|chaufför|g}} * {{Z|tg}}: {{W+|tg|ронанда}}, {{W+|tg|шофёр}} * {{Z|tl}}: {{W+|tl|drayber}} * {{Z|tl}}: {{W+|tl|drayber}} * {{Z|th}}: {{W-|th|คนขับรถ}}, {{W-|th|คนขับ}} * {{Z|te}}: {{W+|te|చోదకుడు}} * {{Z|tr}}: {{W+|tr|sürücü}}, {{W+|tr|şoför}}, {{W-|tr|haydavcı}}, {{W-|tr|yöndemci}}, {{W-|tr|kıvcı}} * {{Z|tk}}: {{W-|tk|sürügi}}, {{W-|tk|şofýor}} * {{Z|bo}}: {{W-|bo|ཁ་ལོ་བ}} * {{Z|ur}}: {{W-|ur|ڈرائیور|n|tr=ḍrāivar}} * {{Z|uk}}: {{W-|uk|воді́й|n}}, {{W-|uk|шофе́р|n}} * {{Z|vi}}: {{W-|vi|người lái}}, {{W+|vi|tài xế}} * {{Z|cy}}: {{W+|cy|gyrrwr|n}} * {{Z|km}}: {{W-|km|អ្នកបើកឡាន}}, {{W-|km|តៃកុង}} * {{Z|yi}}: {{W-|yi|שאָפֿער|n}} * {{Z|el}}: {{W+|el|οδηγός|n|m}} {{werger-bin}} :{{werger çavkanî|en|driver|beş=Ev qismê Wergerê|oldid=75869153}} jm4voyu9o89nr73gxjd13kcyokrmz6d burs 0 21998 6241719 6035781 2026-07-12T00:18:37Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241719 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|burs|mê}} {{navdêr|ku|z=m}} # [[meblex|Meblex]]ek [[dirav]]î ya [[dewlet]] yan [[dezgeh]]ek wek [[diyarî]] dide [[xwendekar]]ekî (bi taybetî ji ber [[biserketî]]bûnê). #: {{hevmaneyên peyvê|ku|stîpend|dermale}} #* {{jêder|ku|jêgirtin=Şaredariya Amedê dê '''burs''' bide 50 hezar zarokan|Kurdishinfo.com, 7/2006}} ==== Jê ==== * {{g|ku|bursdar}} * {{g|ku|bursder}} * {{g|ku|bursiyer}} ==== Etîmolojî ==== Ji {{deyn|fr|ku|bourse}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Stipendium}} {{n}} * {{Z|fi}}: {{W+|fi|stipendi}} * {{Z|fr}}: {{W+|fr|bourse}}, [[érudition]] * {{Z|io}}: {{W+|io|stipendio}}, [[erud-it-eso]] * {{Z|en}}: {{W+|en|scholarship}}, [[bursary]], [[grant-in-aid]] * {{Z|it}}: {{W+|it|borsa|m}} (di studi) * {{Z|sv}}: {{W+|sv|stipendium}} * {{Z|tr}}: {{W+|tr|burs}} {{werger-bin}} == {{ziman|tr}} == === Bilêvkirin === * {{deng|tr|LL-Q256 (tur)-ToprakM-burs.wav|Deng|dever=Îzmîr, Tirkiye}} === Navdêr === {{navdêr|tr}} # [[burs#Kurdî|burs]], [[stîpend]] #* {{bêmînak|tr}} pv6iw5s1pdoms9yk7iu3ypb2biuqkrf wize 0 23990 6241707 6068219 2026-07-11T23:44:47Z Wikihez 7344 /* Jê */ 6241707 wikitext text/x-wiki {{bnr-h|wîze}} == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/wɪˈzɛː/}} * {{kîte|ku|wi|ze}} === Navdêr === {{ku-tewîn-nav|wize|mê|guherto=hemû}} {{navdêr|ku|z=m}} # [[enerjî]], [[vejen]], [[hêz]], [[xurtî]], [[hinêr]], [[taqet]], [[şiyan]], [[qewet]], [[jen]], [[liv]], [[lebat]], [[hereket]] #* {{jêder|ku|jêgirtin=Di gotara xwe de ya bi navê ’Du calcul de l'effet des machines’ [Gaspard Gustave de Coriolis] di sala 1829an de pênasînên nûjen (modern definition) yên kar û '''wizeya''' livînî (kinetic energy) danîn.|Zagrosê Hajo: ''Bandora hêza Coriolis çi ye?'', Netkurd.com, 8/2006}} # {{kontrol|rêz=erê|[[hiz]], [[qudret]]}} ==== Herwiha ==== * [[vize]] * [[wuze]] ==== Jê ==== {{kol3|ku|cure=Jê |bêwize |bêwizehî |bêwizetî |bêwizeyî |biwize |wizedar |wizedarî |wizedarîtî |wizedartî |wizeyî }} ==== Etîmolojî ==== Ji {{deyn|ckb|ku|وزە}}, hevreha {{hv|ku|hizî|w=taqet, wize}}, ji {{paş|ku|hêz|-e}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Energie}} {{m}} * {{Z|ar}}: {{W+|ar|طاقة}} * {{Z|fa}}: {{W+|fa|انرژی}}, {{W+|fa|طاقت}} * {{Z|en}}: {{W+|en|energy}}, {{W+|en|moxie}} * {{Z|tr}}: {{W+|tr|enerji}}, {{W+|tr|erke}}, {{W+|tr|performans}} {{werger-bin}} 3clgpbn8vke46lc0q02wm62yzz2qfo0 6241708 6241707 2026-07-11T23:45:13Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241708 wikitext text/x-wiki {{bnr-h|wîze}} == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/wɪˈzɛː/}} * {{kîte|ku|wi|ze}} === Navdêr === {{ku-tewîn-nav|wize|mê|guherto=hemû}} {{navdêr|ku|z=m}} # [[enerjî]], [[vejen]], [[hêz]], [[xurtî]], [[hinêr]], [[taqet]], [[şiyan]], [[qewet]], [[jen]], [[liv]], [[lebat]], [[hereket]] #* {{jêder|ku|jêgirtin=Di gotara xwe de ya bi navê ’Du calcul de l'effet des machines’ [Gaspard Gustave de Coriolis] di sala 1829an de pênasînên nûjen (modern definition) yên kar û '''wizeya''' livînî (kinetic energy) danîn.|Zagrosê Hajo: ''Bandora hêza Coriolis çi ye?'', Netkurd.com, 8/2006}} # {{kontrol|rêz=erê|[[hiz]], [[qudret]]}} ==== Herwiha ==== * [[vize]] * [[wuze]] ==== Jê ==== {{kol3|ku|cure=Jê |bêwize |bêwizehî |bêwizetî |bêwizeyî |biwize |wizedar |wizedarî |wizedarîtî |wizedartî |wizeyî }} ==== Etîmolojî ==== Ji {{deyn|ckb|ku|وزە}}, hevreha {{hv|ku|hizî|w=taqet, wize}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Energie}} {{m}} * {{Z|ar}}: {{W+|ar|طاقة}} * {{Z|fa}}: {{W+|fa|انرژی}}, {{W+|fa|طاقت}} * {{Z|en}}: {{W+|en|energy}}, {{W+|en|moxie}} * {{Z|tr}}: {{W+|tr|enerji}}, {{W+|tr|erke}}, {{W+|tr|performans}} {{werger-bin}} 2s44iw7vswzohgat15cpdfrlbcyvraj Alîkarî:Nivîsîn 12 25550 6241747 4014723 2026-07-12T11:49:31Z Kewkûrk 15130 Min naveroka gotara heyî zêdekir. 6241747 wikitext text/x-wiki == dêrtin == === Kurdî Kurmancî === ==== Etîmolojî ==== Dêrtin/dartin lêkerekî kevn ê kurmancî ye ku wateyên wê bingehîn ev in: xwedî bûn, hebûn, girtin û parastin. Ji rehê kevn ê îranî tê, ku bi farisî **داشتن (dâštan)** ("hebûn, xwedî bûn, girtin") hevreha ye. Ji rehê proto-hindû-ewropî **\*dʰer-** tê, ku wateya bingehîn ya wê "girtina bi hêz, ragirtin, domandin" e. Hevrehên din: * farisiya kevn: 𐎭𐎠𐎼𐎹𐎫𐎡𐎹 (dārayatiy) — "digire, xwedî ye" * farisiya navîn: dāštan * farisî: داشتن (dâštan) ==== Lêker ==== ===== Wate ===== # xwedî bûn, hebûn # girtin, ragirtin # xwedîkirin, xwedî derketin ==== Di zimanê kurmancî de ==== Lêkerê dêrtin/dartin di axaftina rojane ya kurmanciya nûjen de kêm hatiye bikaranîn û di gelemperî de bi lêkerên **hebûn** û **xwedî bûn** hatiye guherandin. Lêbelê rehê wê di nav peyvên çêkirî de hîn jî dijî: * **maldar** — kesê ku mal heye * **deyndar** — kesê ku deyn heye * **birîndar** — kesê ku birîn heye * **çavdêr** — kesê ku çavdêrî dike * **nobedar** — kesê ku nobet digire * **dîndar** — kesê ku dîn heye * **namûsdar** — kesê ku namûs heye * **ahengdar** — kesê ku aheng heye * **rengdar** — tiştê ku reng heye; reng lê ye * **bangdêr** — kesê ku bang dike Paşgirên **-dar/-dêr** maneya "xwedîbûn, hilgirtin, ragirtin" diparêzin. ==== Tevgerandin ==== ===== Dema niha ===== {| class="wikitable" ! Kes ! Form |- | Ez || didêrim |- | Tu || didêrî |- | Ew/ewa || didêre |- | Em || didêrin |- | Hûn || didêrin |- | Ewna || didêrin |} ===== Borî ya sade ===== {| class="wikitable" ! Kes ! Form |- | Min || dêrî |- | Te || dêrî |- | Wî || dêrî |- | Wê || dêrî |- | Me || dêrî |- | Wan || dêrî |} ===== Borî ya nedîyar / berdewam ===== {| class="wikitable" ! Kes ! Form |- | Min || didêrî |- | Te || didêrî |- | Wî || didêrî |- | Wê || didêrî |- | Me || didêrî |- | We || didêrî |- | Wan || didêrî |} ===== Dema pêşerojê ===== {| class="wikitable" ! Kes ! Form |- | Ez || dê bidêrim |- | Tu || dê bidêrî |- | Ew/ewa || dê bidêre |- | Em || dê bidêrin |- | Hûn || dê bidêrin |- | Ewna || dê bidêrin |} 5g8s197dgu01wg62h3xggo7virmwz3y 6241749 6241747 2026-07-12T11:54:40Z Wikihez 7344 Reverted 1 edit by [[Special:Contributions/Kewkûrk|Kewkûrk]] ([[User talk:Kewkûrk|talk]]): Ji kerema xwe bar bike [[dêrtin]] ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241749 wikitext text/x-wiki {{guherrandin}} Çêkirina rûpelên nû gelek hêsan e. == Rengê sor nîşana tinebûna rûpelê dike == Dema ku tu li peyvê bigerî û nebînî, hingê Wîkîferheng dê peyvê bi rengê '''{{reng2|#d33|sor}}''' binivîse û bibêje ku rûpel bi wî navî tune ye. Her peyva bi rengê sor tê wê wateyê ku ti rûpel bi wî navî tune ye. Pêlî wê peyva rengsor bike û dest bi nivîsîna wê bike. Bala xwe bide ku li şûna peyvên devokî peyvên standard û li her derê tê zanîn bi kar bînî. Ji bo formatê ''binêre'': * '''[[Alîkarî:Formata nivîsînê]]''' * '''[[Alîkarî:Cureyên peyvan]]''' [[Kategorî:Alîkarî]] df2evjlhg9ugbu3yaxn6zgd13lhfdgc zîz bûn 0 37865 6241643 5908735 2026-07-11T18:10:20Z Keyomerd 8814 /* Kurmancî */ 6241643 wikitext text/x-wiki {{bnr-n|zîzbûn}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker 1 === {{ku-tewîn-lk|zîz bûn|form=negerguhêz|niha=b|borî=bû|pêşgir=zîz|valahî=erê}} {{lêker|ku|c=h-ngh}} # {{mane?|ku}} #* {{bêmînak|ku}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|sulk|guman=erê}} * {{Z|tr}}: {{W+|tr|acılaşmak}}, {{W+|tr|duygulanmak}}, {{W-|tr|duygusallaşmak}} {{werger-bin}} === Lêker 2 === {{lêker|ku|c=h-ngh}} # Li dora tiştekî [[zivirîn]]. ==== Jê ==== * {{g|ku|zîzok}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|spin}} {{werger-bin}} tpcnj5vjwgprtfbhhxvgfmvsdz0wusr 6241645 6241643 2026-07-11T18:11:21Z Keyomerd 8814 /* Lêker 2 */ 6241645 wikitext text/x-wiki {{bnr-n|zîzbûn}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker 1 === {{ku-tewîn-lk|zîz bûn|form=negerguhêz|niha=b|borî=bû|pêşgir=zîz|valahî=erê}} {{lêker|ku|c=h-ngh}} # {{mane?|ku}} #* {{bêmînak|ku}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|sulk|guman=erê}} * {{Z|tr}}: {{W+|tr|acılaşmak}}, {{W+|tr|duygulanmak}}, {{W-|tr|duygusallaşmak}} {{werger-bin}} === Lêker 2 === {{lêker|ku|c=h-ngh}} # {{maneid|ku|spin}} Li dora tiştekî [[zivirîn]]. ==== Jê ==== * {{g|ku|zîzok}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|spin}} {{werger-bin}} mhv5llpzytk8z03j6icuqtbt4bwsp6l 6241647 6241645 2026-07-11T18:13:38Z Keyomerd 8814 /* Lêker 2 */ 6241647 wikitext text/x-wiki {{bnr-n|zîzbûn}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker 1 === {{ku-tewîn-lk|zîz bûn|form=negerguhêz|niha=b|borî=bû|pêşgir=zîz|valahî=erê}} {{lêker|ku|c=h-ngh}} # {{mane?|ku}} #* {{bêmînak|ku}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|sulk|guman=erê}} * {{Z|tr}}: {{W+|tr|acılaşmak}}, {{W+|tr|duygulanmak}}, {{W-|tr|duygusallaşmak}} {{werger-bin}} === Lêker 2 === {{lêker|ku|c=h-ngh}} # {{maneid|ku|spin}} Li dora tiştekî [[zivirîn]]. #: {{hevmane|ku|çerixîn}} ==== Jê ==== * {{g|ku|zîzok}} ==== Etîmolojî ==== Ji {{heve|ku|zîz|bûn}}. ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W+|en|spin}} {{werger-bin}} g0i7kma66cpby0bb2xpb57x87g8mz96 ding 0 38625 6241723 6134237 2026-07-12T01:20:14Z Wikihez 7344 /* Jê */ 6241723 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|ding|mê}} {{navdêr|ku|z=m}} # [[deng|Deng]]ekî [[xurt]] lê [[ketin]]ê yan [[lêdan]]ê. #* {{bêmînak|ku}} ==== Jê ==== {{kol3|ku|cure=Jê |ding kirin<q:lêker> |dingkirin<q:navdêr> |dingkirî<q:rengdêr> |dinge-ding |dingandin |dingîn }} ==== Nêzîk ==== * {{g|ku|diring}} * {{g|ku|ting}} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W|fa|دیوار محکم}}, {{W|fa|صدای دُهُل}} * {{Z|en}}: {{W|en|gum}}, {{W|en|ring}}, {{W|en|mainstay|guman=erê}}, {{W|en|spile|guman=erê}}, {{W|en|staddle|guman=erê}}, {{W|en|underpinning|guman=erê}}, {{W|en|spiling|guman=erê}} * {{Z|tr}}: {{W|tr|dink}}, {{W|tr|ring}}, {{W|tr|balya}}, {{W|tr|bağlamak}}, {{W|tr|denk|guman=erê}} {{werger-bin}} == {{ziman|af}} == === Navdêr === {{navdêr|af}} # {{g|ku|tişt}} #* {{bêmînak|af}} === Çavkanî === {{rûpela wergerê|af|tişt}} == {{ziman|fy}} == === Navdêr === {{navdêr|fy|z=nt}} # {{g|ku|tişt}} #* {{bêmînak|fy}} === Çavkanî === {{rûpela wergerê|fy|tişt}} == {{ziman|nl}} == === Navdêr === {{navdêr|nl|z=nt}} # {{g|ku|tişt}} #* {{bêmînak|nl}} === Çavkanî === {{rûpela wergerê|nl|tişt}} == {{ziman|en}} == === Lêker === {{lêker|en}} # [[zengil lê dan]] #* {{bêmînak|en}} === Navdêr === {{navdêr|en}} # dengê zengilê<ref>Ferhenga Kurdî-Îngîlîzî ya Salah Sadallah</ref> #* {{bêmînak|en}} === Çavkanî === {{çavkanî}} sdjm0cfsi8ji08oefj32kdnoy8iqexs çerixîn 0 39428 6241646 6124700 2026-07-11T18:13:11Z Keyomerd 8814 /* Lêker */ 6241646 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{ku-tewîn-lk|çerixîn|form=negerguhêz|niha=çerix|borî=çerix}} {{lêker|ku|c=x-ngh}}, {{ç-ya req}}, {{r-ya nerm}} # {{g|ku|zîz bûn|id=spin}}, [[çerx]] dan, [[dewr]] dan, li [[dor]] tiştekî [[zivirîn]] #* {{jêder|ku|jêgirtin=Heta refên valahiyê jî di nav bêdengiya xwe de '''diçerixîn''' û gêr dibûn.|{{Jêgirtin/Mehmed Uzun/Mirina Kalekî Rind/1987}}}} # {{f|ku|Qoser}} [[şemitîn]] #* {{bêmînak|ku}} ==== Ji wêjeya klasîk ==== * {{jêder|ku|{{Jêgirtin/Melayê Cizîrî/Dîwana Melayê Cizirî}}|jêgirtin=Bihnek ji wisalê me bihîst û kerixîm ez</br>Wek tole li pê mûçih li dorê '''çerixîm''' ez</br>Çix kir me hebîbî ko tu narî biqeşî}} ==== Bi alfabeyên din ==== * {{ku-ar|چه‌رخین}} ==== Herwiha ==== * [[çerxîn]] ==== Tewîn ==== ''Lêker'': :-çerix- ==== Têkildar ==== * [[çerxandin]] ==== Etîmolojî ==== Ji {{qertaf|ku|çerx|-în}}. ==== Jê ==== * [[çerixiyayî]] * [[çerixî]] * [[çerixok]] ==== Bi zaravayên din ==== * {{Z|ckb}}: {{W-|ckb|سووڕان}}, {{W-|ckb|چەرخان}}, {{W-|ckb|خولان}}, {{W-|ckb|خولانەوە}}, {{W-|ckb|خول خواردن}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|aufwirbeln}} * {{Z|ar}}: {{W-|ar|أقبل|guman=erê}} * {{Z|fa}}: {{W+|fa|چرخیدن}}, {{W+|fa|چرخیدن}} * {{Z|en}}: {{W+|en|turn}}, {{W+|en|slipping}}, {{W+|en|sliding}}, {{W+|en|skidding}} * {{Z|tr}}: {{W+|tr|deveran}}, {{W+|tr|dolaşmak}}, {{W+|tr|dönelemek}}, {{W+|tr|kaymak}}, {{W+|tr|sıyrılma}}, {{W+|tr|sıyrılmak}}, {{W+|tr|sürçme}}, {{W+|tr|sürçmek}}, {{W+|tr|deveran etmek|guman=erê}}, {{W-|tr|kendi ekseni etrafında dönmek|guman=erê}} {{werger-bin}} === Navdêr === {{ku-tewîn-nav|çerixîn|mê}} {{navdêr|ku|z=m}} # {{bêwate}} #* {{bêmînak|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} kwqjvf57xcpud7iqdqrbq204b0ixcgn zift 0 43774 6241666 6135107 2026-07-11T20:35:47Z Wikihez 7344 [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin 6241666 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:EPAoilspillsubdivision5.jpg|thumb|zift]] {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e û bi taybetî bo [[ava]]kirina [[kolan]]an tê [[bikaranîn]]. #: {{hevmane|ku|qîr|qetran|asfalt}} #* {{jêder|ku|jêgirtin=Li ser riya qîr û '''zift''' / Hatin ser hev pale gişt|{{Jêgirtin/Firat Cewerî/Çîroka Malbata Evdo/1999}}}} # [[made|Made]]yê ku [[berî]] [[rê]]yekê [[qîr]] bikin [[danan|didanin]]. ==== Jê ==== {{kol3|ku|cure=Jê |zift kirin<pos:lêker> |ziftkirin<pos:navdêr> |ziftkirî<pos:rengdêr> |ziftbûyî<pos:rengdêr> |ziftî }} ==== Bi alfabeyên din ==== * {{ku-ar|زفت}} ==== Bide ber ==== * {{g|ku|zeft}} ==== Etîmolojî ==== Ji {{ji|ar|ku|زفت|tr=zift}} ji {{ji|arc|ku||zipta}}. Hevreha {{hv|akk||ziptu|sc=Latn}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Asphalt|n}}, {{W+|de|Bitumen|m|guman=erê}} * {{Z|fa}}: {{W+|fa|آسفالت}}, {{W+|fa|قیر}} * {{Z|en}}: {{W+|en|bitumen}}, {{W+|en|pitch}}, {{W+|en|tar}} * {{Z|tr}}: {{W+|tr|asfalt}}, {{W+|tr|zabıt}}, {{W+|tr|zapt}}, {{W+|tr|zift}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[qîr]], [[zift]] #* {{bêmînak|tr}} ecmdfjr2kp0qg02g6h523r9l13br3ye 6241667 6241666 2026-07-11T20:36:05Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241667 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:EPAoilspillsubdivision5.jpg|thumb|zift]] {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e û bi taybetî bo [[ava]]kirina [[kolan]]an tê [[bikaranîn]]. #: {{hevmane|ku|qîr|qetran|asfalt}} #* {{jêder|ku|jêgirtin=Li ser riya qîr û '''zift''' / Hatin ser hev pale gişt|{{Jêgirtin/Firat Cewerî/Çîroka Malbata Evdo/1999}}}} # [[made|Made]]yê ku [[berî]] [[rê]]yekê [[qîr]] bikin [[danan|didanin]]. ==== Bi alfabeyên din ==== * {{ku-ar|زفت}} ==== Jê ==== {{kol3|ku|cure=Jê |zift kirin<pos:lêker> |ziftkirin<pos:navdêr> |ziftkirî<pos:rengdêr> |ziftbûyî<pos:rengdêr> |ziftî }} ==== Bide ber ==== * {{g|ku|zeft}} ==== Etîmolojî ==== Ji {{ji|ar|ku|زفت|tr=zift}} ji {{ji|arc|ku||zipta}}. Hevreha {{hv|akk||ziptu|sc=Latn}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Asphalt|n}}, {{W+|de|Bitumen|m|guman=erê}} * {{Z|fa}}: {{W+|fa|آسفالت}}, {{W+|fa|قیر}} * {{Z|en}}: {{W+|en|bitumen}}, {{W+|en|pitch}}, {{W+|en|tar}} * {{Z|tr}}: {{W+|tr|asfalt}}, {{W+|tr|zabıt}}, {{W+|tr|zapt}}, {{W+|tr|zift}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[qîr]], [[zift]] #* {{bêmînak|tr}} 8741pokicn1oucbd3rji88vxibq9om0 asfalt 0 43775 6241657 6095491 2026-07-11T20:16:11Z Wikihez 7344 /* Navdêr */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin 6241657 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{ku-tewîn-nav|asfalt|mê}} {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e û bi taybetî bo [[ava]]kirina [[kolan]]an tê [[bikaranîn]]. #: {{hevmane|ku|qîr|qetran|zift}} #* {{bêmînak|ku}} ==== Jê ==== {{kol3|ku|cure=Jê |asfalt kirin<q:lêker> |asfaltkirin<q:navdêr> |asfaltî }} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|asfalt}}, {{W-|af|bergpik}} * {{Z|de}}: {{W+|de|Asphalt|m}}, {{W-|de|Erdpech}} * {{Z|id}}: {{W+|id|aspal}} * {{Z|eo}}: {{W+|eo|asfalto}} * {{Z|fa}}: {{W+|fa|آسفالت}} * {{Z|fi}}: {{W+|fi|asvaltti}} * {{Z|fr}}: {{W+|fr|asphalte}} * {{Z|nl}}: {{W+|nl|asfalt}} * {{Z|he}}: {{W+|he|כֹּפֶר|tr=kfar}} * {{Z|en}}: {{W+|en|asphalt}}, {{W+|en|blacktop}} * {{Z|it}}: {{W+|it|asfalto}} * {{Z|is}}: {{W-|is|asfalt}}, {{W+|is|malbik}} * {{Z|ca}}: {{W+|ca|asfalt}} * {{Z|la}}: {{W-|la|bitumen}} * {{Z|hu}}: {{W+|hu|aszfalt}} * {{Z|pap}}: {{W-|pap|asfalt}} * {{Z|pt}}: {{W+|pt|asfalto}} * {{Z|ru}}: {{W+|ru|асфальт}} * {{Z|es}}: {{W+|es|asfalto}} * {{Z|sv}}: {{W-|sv|jordbeck}} * {{Z|tr}}: {{W+|tr|asfalt}} * {{Z|el}}: {{W+|el|άσφαλτος}} {{werger-bin}} == {{ziman|tr}} == === Bilêvkirin === * {{deng|tr|LL-Q256 (tur)-Veravi95-asfalt.wav|Deng|dever=}} === Navdêr === {{navdêr|tr}} # [[qîr]] #* {{bêmînak|tr}} # [[qetran]], asfalt #* {{bêmînak|tr}} # [[asfaltkirî]] #: {{mk|tr|uzun bir '''asfalt''' yol üzerinde koştuk|me li ser riyeke dirêj a asfatkirî baz dan}} 1pska8wwj1qtd5aa508n96hkky1v4fk 6241658 6241657 2026-07-11T20:17:05Z Wikihez 7344 /* Navdêr */ 6241658 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{ku-tewîn-nav|asfalt|mê}} {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e û bi taybetî bo [[ava]]kirina [[kolan]]an tê [[bikaranîn]]. #: {{hevmane|ku|qîr|qetran|zift}} #* {{bêmînak|ku}} ==== Jê ==== {{kol3|ku|cure=Jê |asfalt kirin<q:lêker> |asfaltkirin<q:navdêr> |asfaltî }} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|asfalt}}, {{W-|af|bergpik}} * {{Z|de}}: {{W+|de|Asphalt|m}}, {{W-|de|Erdpech}} * {{Z|id}}: {{W+|id|aspal}} * {{Z|eo}}: {{W+|eo|asfalto}} * {{Z|fa}}: {{W+|fa|آسفالت}} * {{Z|fi}}: {{W+|fi|asvaltti}} * {{Z|fr}}: {{W+|fr|asphalte}} * {{Z|nl}}: {{W+|nl|asfalt}} * {{Z|he}}: {{W+|he|כֹּפֶר|tr=kfar}} * {{Z|en}}: {{W+|en|asphalt}}, {{W+|en|blacktop}} * {{Z|it}}: {{W+|it|asfalto}} * {{Z|is}}: {{W-|is|asfalt}}, {{W+|is|malbik}} * {{Z|ca}}: {{W+|ca|asfalt}} * {{Z|la}}: {{W-|la|bitumen}} * {{Z|hu}}: {{W+|hu|aszfalt}} * {{Z|pap}}: {{W-|pap|asfalt}} * {{Z|pt}}: {{W+|pt|asfalto}} * {{Z|ru}}: {{W+|ru|асфальт}} * {{Z|es}}: {{W+|es|asfalto}} * {{Z|sv}}: {{W-|sv|jordbeck}} * {{Z|tr}}: {{W+|tr|asfalt}} * {{Z|el}}: {{W+|el|άσφαλτος}} {{werger-bin}} == {{ziman|tr}} == === Bilêvkirin === * {{deng|tr|LL-Q256 (tur)-Veravi95-asfalt.wav|Deng|dever=}} === Navdêr === {{navdêr|tr}} # [[qîr]] #* {{bêmînak|tr}} # [[qetran]], {{g|ku|asfalt}} #* {{bêmînak|tr}} === Rengdêr === {{rengdêr|tr}} # [[asfaltkirî]] #: {{mk|tr|uzun bir '''asfalt''' yol üzerinde koştuk.|Me li ser riyeke dirêj a asfatkirî baz dan.}} 6ykixsbiy2y50d006jcct2bofro9qk6 6241659 6241658 2026-07-11T20:17:26Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241659 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{ku-tewîn-nav|asfalt|mê}} {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e û bi taybetî bo [[ava]]kirina [[kolan]]an tê [[bikaranîn]]. #: {{hevmane|ku|qîr|qetran|zift}} #* {{bêmînak|ku}} ==== Jê ==== {{kol3|ku|cure=Jê |asfalt kirin<q:lêker> |asfaltkirin<q:navdêr> |asfaltî }} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|asfalt}}, {{W-|af|bergpik}} * {{Z|de}}: {{W+|de|Asphalt|m}}, {{W-|de|Erdpech}} * {{Z|id}}: {{W+|id|aspal}} * {{Z|eo}}: {{W+|eo|asfalto}} * {{Z|fa}}: {{W+|fa|آسفالت}} * {{Z|fi}}: {{W+|fi|asvaltti}} * {{Z|fr}}: {{W+|fr|asphalte}} * {{Z|nl}}: {{W+|nl|asfalt}} * {{Z|he}}: {{W+|he|כֹּפֶר|tr=kfar}} * {{Z|en}}: {{W+|en|asphalt}}, {{W+|en|blacktop}} * {{Z|it}}: {{W+|it|asfalto}} * {{Z|is}}: {{W-|is|asfalt}}, {{W+|is|malbik}} * {{Z|ca}}: {{W+|ca|asfalt}} * {{Z|la}}: {{W-|la|bitumen}} * {{Z|hu}}: {{W+|hu|aszfalt}} * {{Z|pap}}: {{W-|pap|asfalt}} * {{Z|pt}}: {{W+|pt|asfalto}} * {{Z|ru}}: {{W+|ru|асфальт}} * {{Z|es}}: {{W+|es|asfalto}} * {{Z|sv}}: {{W-|sv|jordbeck}} * {{Z|tr}}: {{W+|tr|asfalt}} * {{Z|el}}: {{W+|el|άσφαλτος}} {{werger-bin}} == {{ziman|tr}} == === Bilêvkirin === * {{deng|tr|LL-Q256 (tur)-Veravi95-asfalt.wav|Deng|dever=}} === Navdêr === {{navdêr|tr}} # [[qîr]] #* {{bêmînak|tr}} # [[qetran]], {{g|ku|asfalt}} #* {{bêmînak|tr}} === Rengdêr === {{rengdêr|tr}} # [[asfaltkirî]] #: {{mk|tr|Uzun bir '''asfalt''' yol üzerinde koştuk.|Me li ser riyeke dirêj a asfatkirî baz dan.}} 00c1a1nmhi2dqo64p42kuc66cnp6mal -nî 0 44711 6241689 6231032 2026-07-11T22:33:01Z Wikihez 7344 /* Paşgir */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin 6241689 wikitext text/x-wiki {{bnr-h|ni|nî|ni-|-nî|Ni}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Paşgir === {{paşgir|ku}} # [[paşgir]]ek e ku pê hin [[rengdêr]] ji [[hoker]]an tên [[çêkirin]] #: {{qfnim|ku|erê|erênî}} #: {{qfnim|ku|bila|bilanî}} #: {{qfnim|ku|neyî|neyînî}} # [[paşgir]]ek ku hin formên duyem yên [[hoker]]an pê tên çêkirin: #: {{qfnim|ku|heta|hetanî}} #: {{qfnim|ku|heya|heyanî}} #: {{qfnim|ku|mîna|mînanî}} #: {{qfnim|ku|nola|nolanî}} #: {{qfnim|ku|fena|fenanî}} # {{e|ku|Reşwî|Koçgîrî|Xorasanî}} kesê yekem yê pirjimar di dema niha de #* {{jêder|ku|jêgirtin=Min henek pere danê lê ne bi dilê min bû</br>Min çay îkramê kir</br>Gotin ecela me heye em ê dereng bimê'''nî'''|ji kovareke Bîrnebûnê, http://birnebun.eu/hejmar/birnebunweb43.pdf}} ==== Têkildar ==== * {{g|ku|-ahî}} * {{g|ku|-anî}} * {{g|ku|-atî}} * {{g|ku|-ayî}} * {{g|ku|-î}} * {{g|ku|-îtî}} * {{g|ku|-tî}} ==== Jê ==== {{paşgirbibîne|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} [[Kategorî:Koçgîrî]] 6oh65fwcf57no9c7ath53vf5jjbifg2 qîr 0 52822 6241665 6235169 2026-07-11T20:33:05Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241665 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr 1 === [[Wêne:106 cunetas asfalto calle sucre (12523244613).jpg|thumb|qîr]] {{navdêr|ku|z=m}} # Tiştek [[reş]], [[çir]], [[ron]] û [[don]] e. #: {{hevmaneyên peyvê|ku|qetran}} #* {{jêder|ku|jêgirtin=(...) derkevin ser riyeke '''qîr''' û zift, hûn ê ji wir jî dakevin jêr (...)|''[[w:Dara Hinarê|Dara Hinarê]]'', [[w:Yaşar Kemal|Yaşar Kemal]], Weşanên [[w:Nûdem|Nûdem]]}} #* {{jêder|ku|{{Jêgirtin/Ehmedê Xanî/Mem û Zîn}}|jêgirtin=Kîjek 'ereban e lêvdeqandî</br>Ser ta bi piyan reş e wekî '''qîr'''</br>Ne la'iqê behs û xwestina mîr«}} ==== Bide ber ==== * {{g|ku|asfalt}} * {{g|ku|çîmento}} * {{g|ku|gêç}} * {{g|ku|seb}} ==== Jê ==== * {{g|ku|qîr kirin}} * {{g|ku|qîrkirin}} * {{g|ku|qîrkirî}} * {{g|ku|qîrî}} ==== Etîmolojî ==== Ji {{ji|akk|ku|tr=qîru}}. ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|katran}} * {{Z|de}}: {{W+|de|Teer|m}}, {{W+|de|Bitumen|m|guman=erê}} * {{Z|da}}: {{W+|da|tjære}} * {{Z|ar}}: {{W-|ar|قَطْران|tr=qetran}} * {{Z|eo}}: {{W-|eo|gudro}} * {{Z|fa}}: {{W+|fa|داد}}, {{W-|fa|فریاد بلند}}, {{W-|fa|کلاغ سیاه}}, {{W+|fa|قیر}}, {{W+|fa|قیر|guman=erê}} * {{Z|fo}}: {{W-|fo|tjøra}} * {{Z|fi}}: {{W+|fi|terva}} * {{Z|fr}}: {{W+|fr|goudron|m}} * {{nl}}. [[teer]] * {{Z|he}}: {{W+|he|זפת}} * {{Z|ang}}: {{W-|ang|tierwe}}, {{W-|ang|teoro}} * {{Z|en}}: {{W+|en|tar}}, {{W+|en|asphalt}}, {{W+|en|pitch}}, {{W+|en|bitumen|guman=erê}}, * {{Z|it}}: {{W+|it|catrame}} * {{Z|is}}: {{W-|is|tjara}} * {{Z|ca}}: {{W+|ca|quitrà|m}} * {{Z|hu}}: {{W+|hu|kátrány}} * {{Z|pl}}: {{W-|pl|Smoła}} * {{Z|pt}}: {{W+|pt|alcatrão}} * {{Z|ru}}: {{W+|ru|Дёготь}} * {{Z|sh}}: {{W+|sh|katran|m}} * {{Z|sh}}: {{W+|sh|katran|m}} * {{Z|sh}}: *: Kirîlî: [[катран]] {{m}} *: Latînî: {{W-|la|katran|m}} * {{Z|es}}: {{W+|es|alquitrán|m}}, {{W+|es|brea}} * {{Z|sv}}: {{W+|sv|tjära|c}} * {{Z|tr}}: {{W+|tr|katran}}, {{W+|tr|asfalt}}, {{W+|tr|çığlık}}, {{W+|tr|haykırı}}, {{W+|tr|nara}}, {{W+|tr|zift}} * {{Z|vi}}: {{W+|vi|hắc ín}} {{werger-bin}} === Rengdêr === {{rengdêr|ku}} # {{f|ku|reng}} wek qîrê [[reş]], [[pir]] [[reş]] #* {{bêmînak|ku}} # qîr[[reş]], ango [[pir]] [[reş]] e, #: {{mk|ku|Mirîşkek qîreş li naviya gund peyda bû.}} ==== Werger ==== {{werger-ser}} {{werger-bin}} === Navdêr 2 === {{ku-tewîn-nav|qîr|mê}} {{navdêr|ku|z=m}} # [[qîrîn]], [[qîjîn]], [[hewar]], [[gazî]], [[fîxan]], [[deng]]ê [[bilind]] #* {{bêmînak|ku}} ==== Herwiha ==== * {{g|ku|qêr}} * {{g|ku|qêrr}} * {{g|ku|qîrr}} ==== Jê ==== * {{g|ku|qîrrandin}} * {{g|ku|qîrrandî}} * {{g|ku|qîrîn}} ==== Etîmolojî ==== Ji {{ji|arc|ku|ܩܪܐ|tr=q-r-a-|w=[[gazî]] kirin, [[bang]] kirin, [[qîrîn]], bi dengê bilind [[xwandin]]}}, hevreha {{hv|he|קריאה}} (qirîa: qîrîn, xwandin), erebî {{g|ar|قرء}} (q-r-e-: [bi dengê bilind] [[xwandin]]). Ji eynî rehî: [[Qur'an]], [[qiraet]]. ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|القار|guman=erê}}, {{W-|ar|القیر|guman=erê}} * {{Z|tr}}: {{W+|tr|nara}} {{werger-bin}} 8q4pum3m3p1xeelmmw2m6ft5z35gzad Tewandin:gotin 106 61042 6241693 6238354 2026-07-11T22:49:34Z Mehmet1922 14058 6241693 wikitext text/x-wiki == Reh == '''Rehên dema niha''': * Standard: -bêj- * Devkî: -bê- (kurmanciya navendî û rojhilatî) * Devokî: ** -vê- (kurmanciya serhedî) ** -wê- (kurmanciya rojavayî û xorasanî) ** -wegî- (Şingal) {{çp}} == Tabloya tewandinê == {{etîket tewandin |etîket1 = Standard |naverok1 = {{ku-tewandin|gotin|form=gerguhêz|niha=bêj|borî=got |tablo=ergatîv}} |etîket2 = Devkî: kurmanciya navendî |naverok2 = {{ku-tewandin|gotin|form=gerguhêz|niha=bê|borî=go}} |etîket3 = Devkî: kurmanciya rojhilatî |naverok3 = {{ku-tewandin|gotin|form=gerguhêz|niha=bê|borî=go|devok=rojhilatî}} |etîket4 = Kurmanciya serhedî |naverok4 = {{ku-tewandin|gotin|form=gerguhêz|niha=vê|borî=go}} |etîket5 = Kurmanciya rojavayî |naverok5 = {{ku-tewandin|gotin|form=gerguhêz|niha=wê|borî=go}} }} ijp4zinw2qqfwtw8m7eow0j8dmypqck Tewandin:kirin 106 61065 6241685 6237839 2026-07-11T22:26:56Z Mehmet1922 14058 6241685 wikitext text/x-wiki {{etîket tewandin |etîket1 = Standard, kurmanciya navendî, rojavayî û serhedî |naverok1 = {{ku-tewandin|kirin|form=gerguhêz|niha=k|borî=kir |tablo=ergatîv}} |etîket2 = Kurmanciya rojhilatî |naverok2 = {{ku-tewandin|kirin|form=gerguhêz|niha=ke|borî=kir|devok=rojhilatî}} }} k2jheqptr5qlqxb0fdywn9u5jah02kr divançe 0 132635 6241695 4609211 2026-07-11T23:17:17Z Wikihez 7344 /* {{ziman|tr}} */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: +[[Şablon:îzah|îzah]] 6241695 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[dîwançe]] {{îzah|dîwana biçûk a helbestan}} q5up1mgwgnq1wjxsg8w4gyumi9g58oy 6241700 6241695 2026-07-11T23:30:46Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241700 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # {{e|tr|şiîr}} [[dîwançe]] {{îzah|dîwana biçûk a helbestan}} sl79gqx5tg25t9c4mlgj771zxtitf9c lenguîstîk 0 383836 6241710 6171051 2026-07-11T23:54:40Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241710 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[zimanzanî]], [[zimannasî]], [[fîlolojî]] ==== Herwiha ==== * {{hw|ku|lînguîstîk|lingwistîk}} ==== Etîmolojî ==== Ji {{qertaf|ku|lenguîstî|-k}}. ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W+|fa|زبانشناسی}} * {{Z|tr}}: {{W+|tr|dil bilimi}}, {{W+|tr|lisaniyet}} {{werger-bin}} jxfbx4eh7jpyt285kvwq6zvujaoa1tp spin 0 409494 6241644 6093698 2026-07-11T18:11:00Z Keyomerd 8814 /* Lêker */ 6241644 wikitext text/x-wiki == {{ziman|nl}} == === Navdêr === {{navdêr|nl|z=m}} # {{mijar|nl|heywan}} {{g|ku|tevnpîrk}} === Çavkanî === {{rûpela wergerê|nl|tevnpîrk}} == {{ziman|en}} == === Bilêvkirin === * {{deng|en|en-us-spin.ogg|dever=DYA}} * {{deng|en|en-au-spin.ogg|dever=Awistralya}} === Lêker === {{en-tewîn-lk|form=awarte|n3y=spins|b=spun|pb=spun|pn=spinning}} {{lêker|en}} # {{g|ku|zîz bûn|id=spin}} === Navdêr === # {{f|en|fizîk}} [[spîn]] fay80daw7hz0vx3zq99b4c91mn422xz 6241648 6241644 2026-07-11T18:13:53Z Keyomerd 8814 /* Lêker */ 6241648 wikitext text/x-wiki == {{ziman|nl}} == === Navdêr === {{navdêr|nl|z=m}} # {{mijar|nl|heywan}} {{g|ku|tevnpîrk}} === Çavkanî === {{rûpela wergerê|nl|tevnpîrk}} == {{ziman|en}} == === Bilêvkirin === * {{deng|en|en-us-spin.ogg|dever=DYA}} * {{deng|en|en-au-spin.ogg|dever=Awistralya}} === Lêker === {{en-tewîn-lk|form=awarte|n3y=spins|b=spun|pb=spun|pn=spinning}} {{lêker|en}} # {{g|ku|zîz bûn|id=spin}}, [[çerixîn]] === Navdêr === # {{f|en|fizîk}} [[spîn]] bosb83o558nfkapxkkfxdr095cgf3xb 6241649 6241648 2026-07-11T18:37:29Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241649 wikitext text/x-wiki == {{ziman|nl}} == === Navdêr === {{navdêr|nl|z=m}} # {{mijar|nl|heywan}} {{g|ku|tevnpîrk}} === Çavkanî === {{rûpela wergerê|nl|tevnpîrk}} == {{ziman|en}} == === Bilêvkirin === * {{deng|en|en-us-spin.ogg|dever=DYA}} * {{deng|en|en-au-spin.ogg|dever=Awistralya}} === Lêker === {{en-tewîn-lk|form=awarte|n3y=spins|b=spun|pb=spun|pn=spinning}} {{lêker|en}} # {{g|ku|zîz bûn|id=spin}}, [[çerixîn]] === Navdêr === {{navdêr|en}} # {{f|en|fizîk}} [[spîn]] sigl0ooqby4wnfb0pu9446j4omvnacn wîze 0 540737 6241705 6018952 2026-07-11T23:44:15Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241705 wikitext text/x-wiki {{bnr-h|wize}} == {{ziman|ku}} == === Navdêr === {{navdêr|ku}} # misadeya têketinê, [[destûra têketinê]] ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Einreiseerlaubnis}} * {{Z|tr}}: {{W+|tr|vize}} {{werger-bin}} kok1cbtpcj44blm3gzhgbqwmieioxg0 6241706 6241705 2026-07-11T23:44:27Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241706 wikitext text/x-wiki {{bnr-h|wize}} == {{ziman|ku}} == === Navdêr === {{navdêr|ku|c=m}} # misadeya têketinê, [[destûra têketinê]] ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Einreiseerlaubnis}} * {{Z|tr}}: {{W+|tr|vize}} {{werger-bin}} qrltr5wqnutt49zdgw5s8ax4l7j7ueb Tewandin:dan 106 608981 6241691 5142068 2026-07-11T22:41:35Z Mehmet1922 14058 6241691 wikitext text/x-wiki {{etîket tewandin |etîket1 = Standard û kurmanciya navendî, rojavayî û serhedî |naverok1 = {{ku-tewandin|dan|form=gerguhêz|niha=d|borî=da |tablo=ergatîv}} |etîket2 = Kurmanciya rojhilatî |naverok2 = {{ku-tewandin|dan|form=gerguhêz|niha=de|borî=da}} }} bma2ctoyfngb73pzyo2w2ruf7qm81sm Tewandin:zanîn 106 609015 6241688 6236995 2026-07-11T22:32:34Z Mehmet1922 14058 6241688 wikitext text/x-wiki == Reh == Dema niha: {{g|ku|-zan-}} '''Ne-erênî:''' * ''dema niha ya giştî û dema bêt'': '''nizan-''' * ''dema niha ya berdewam'': '''nedizan-''' * ''demên borî'': '''ne(-)zan-''' == Tabloya tewandinê == {{ku-tewandin|zanîn|form=gerguhêz|niha=zan|borî=zanî |tablo=ergatîv}} 6pf0g5wcclv51sjz8439kwim06oduv6 Tewandin:bihîstin 106 609076 6241690 6236998 2026-07-11T22:39:37Z Mehmet1922 14058 6241690 wikitext text/x-wiki == Reh == '''Rehên dema niha''': -bîz-, -bîs-, -bê-, -bihîz- == Tabloya tewandinê == {{ku-tewandin|bihîstin|form=gerguhêz|niha=bîz|borî=bihîst |tablo=ergatîv}} 2j1qxgmqlteg9zs1x7y08ynfdnx1nkf Tewandin:fêm kirin 106 672012 6241694 4522301 2026-07-11T23:01:52Z Mehmet1922 14058 6241694 wikitext text/x-wiki {{ku-tewandin|fêm kirin |form=gerguhêz|niha=k|borî=kir|pêşgir=fêm|valahî=erê |tablo=ergatîv}} 852qa6dww4bvdv6fs84fjbbijan08mo Tewandin:rawestandin 106 730021 6241687 4523026 2026-07-11T22:28:50Z Mehmet1922 14058 6241687 wikitext text/x-wiki {{ku-tewandin|rawestandin|form=gerguhêz|niha=westîn|borî=westand|pêşgir=ra |tablo=ergatîv}} b5zhf8nmud25xe5bbqp604up6ufupgt Şablon:p-mane 10 843285 6241650 5094212 2026-07-11T18:56:45Z Wikihez 7344 6241650 wikitext text/x-wiki <u id="p-mane"><!-- -->{{#if:{{{1|}}}|<u style="text-decoration: underline red;">{{{1|}}}</u>}}</u><sup class="plainlinks"><nowiki>[</nowiki>[[Wîkîferheng:Daxwazên peyitandinê#{{PAGENAME}}|Ji bo vê maneyê '''çavkanî''' hewce ye]]. [{{fullurl:Wîkîferheng:Daxwazên peyitandinê|action=edit&section=new&preload=Şablon:p-wate/preload&preloadtitle=%5B%5B{{urlencode:{{FULLPAGENAME}}}}%23p-mane%7c{{urlencode:{{FULLPAGENAME}}}}%5D%5D}} (+)]&nbsp;]</sup> <includeonly>[[Kategorî:Maneyên bêçavkanî]]</includeonly><noinclude> {{belgekirin}} </noinclude> dh2rr6fat37ys0jhnpkcjutvbn2b6cp Bikarhêner:Wikihez/common.js 2 873671 6241683 6241075 2026-07-11T22:23:55Z Wikihez 7344 6241683 javascript text/javascript mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/loader.js&action=raw&ctype=text/javascript') mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/formatherf.js&action=raw&ctype=text/javascript') importScript( 'Bikarhêner:Wikihez/skrîpt/js/copyTitle.js' ); // Backlink: [[Bikarhêner:Wikihez/skrîpt/js/copyTitle.js]] // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/addAutoCat.js&action=raw&ctype=text/javascript'); importScript( 'Bikarhêner:Wikihez/newentrywiz.js' ); // Backlink: [[Bikarhêner:Wikihez/newentrywiz.js]] //[[Bikarhêner:Wikihez/skrîpt/js/VisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/VisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/CreateTranslation.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/CreateTranslation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/defaultVisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/defaultVisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/wergerîne.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/wergerîne.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/getinflections.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/getinflections.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/templateScript2.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/templateScript2.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/şablon-lêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/şablon-lêke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/editor.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/LanguageUtils.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/LanguageUtils.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-QQ.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-QQ.js&action=raw&ctype=text/javascript'); //[[:w:Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js]] mw.loader.load('//ku.wikipedia.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/test.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/test.js&action=raw&ctype=text/javascript'); // This array of dependencies comes from [[MediaWiki:Gadgets-definition]]. // If the list of dependencies changes, copy the text after dependencies= // for TranslationAdder and run console.log(JSON.stringify("paste dependencies here".split(/, ?/))) // in your browser's JavaScript console. Put the resulting array as the first argument to mw.loader.using. //[[User:Wikihez/skrîpt/js/TranslationAdder.js]] //mw.loader.using(["ext.gadget.LegacyScriptsNewNode","mediawiki.cookie","mediawiki.util"], //function() { // importScript('User:Wikihez/skrîpt/js/TranslationAdder.js'); //}); mw.loader.load('https://en.wikipedia.org/w/index.php?title=User:BrandonXLF/TodoList.js&action=raw&ctype=text/javascript'); /* // [[:w:en:MediaWiki:Gadget-edittop.js]] mw.loader.load('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-edittop.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/addAutoCat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Balyozbot/Gadget-CommonWikt.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Balyozbot/Gadget-CommonWikt.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/hw-ceke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/hw-ceke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/sort-langheaders.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/sort-langheaders.js&action=raw&ctype=text/javascript'); //[[:en:User:Conrad.Irwin/Api.js]] mw.loader.load('//en.wiktionary.org/w/index.php?title=User:Conrad.Irwin/Api.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/etîket-çêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/etîket-çêke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/tagger.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/tagger.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-CatMaker.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-CatMaker.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/VisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/VisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/XMLize.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/XMLize.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/RhymesAdder.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/RhymesAdder.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Editor.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-aWa.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-aWa.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/FilterTranslations.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/FilterTranslations.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/custom.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/custom.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/reformat.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/reformat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/templateScript.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/templateScript.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/translateWiki.js]] ji aliyê [[Bikarhêner:Guherto]], [[Taybet:PermanentLink/4854098#Translatewiki.net]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/translateWiki.js&action=raw&ctype=text/javascript'); // Various fixes for the trees generated by [[Module:family tree]]. $(function () { // Show the top toggle. $('.familytree-toptoggle').css('display', ''); // Initialize the text of the toggles. $('.familytree').get().forEach(function (tree) { var isCollapsed = tree.classList.contains('mw-collapsed'); var toggles = $(tree).find('.familytree-toggle'); if (toggles[0]) { var customToggleClass = Array.prototype.filter.call(toggles[0].classList, function (className) { return className.indexOf('mw-customtoggle-familytree') === 0; })[0]; if (customToggleClass) { var toggledElement = $('#' + customToggleClass.replace('mw-customtoggle', 'mw-customcollapsible')); if (toggledElement) { toggles.html(toggledElement.data(isCollapsed ? 'expandtext' : 'collapsetext')); } } } }); // Change the text in the custom toggles generated by [[Module:family tree]] // when they are clicked. $('.mw-collapsible').on('beforeExpand.mw-collapsible beforeCollapse.mw-collapsible', function (event) { if (this.id.indexOf('mw-customcollapsible-familytree') === 0) { var toggle = $('.' + this.id.replace('mw-customcollapsible', 'mw-customtoggle')); if (event.type === 'beforeExpand') { toggle.html(this.dataset.collapsetext); } else { // beforeCollapse toggle.html(this.dataset.expandtext); } event.stopPropagation(); } }); }); */ mw.util.addPortletLink( mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions', '/w/index.php?title=' + mw.config.get('wgPageName') + '&action=edit&editintro=User:Wikihez/usenec', 'nec', 'id', 'use the New Entry Creator to create a new entry', 'a', 'nextnode'); lf5euyjk555370v8lxvle0ayj76zi1e 6241692 6241683 2026-07-11T22:41:40Z Wikihez 7344 Restored revision 6241075 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241692 javascript text/javascript mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/loader.js&action=raw&ctype=text/javascript') importScript( 'Bikarhêner:Wikihez/skrîpt/js/copyTitle.js' ); // Backlink: [[Bikarhêner:Wikihez/skrîpt/js/copyTitle.js]] // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/addAutoCat.js&action=raw&ctype=text/javascript'); importScript( 'Bikarhêner:Wikihez/newentrywiz.js' ); // Backlink: [[Bikarhêner:Wikihez/newentrywiz.js]] //[[Bikarhêner:Wikihez/skrîpt/js/VisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/VisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/CreateTranslation.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/CreateTranslation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/defaultVisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/defaultVisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/wergerîne.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/wergerîne.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/getinflections.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/getinflections.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/templateScript2.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/templateScript2.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/şablon-lêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/şablon-lêke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/editor.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/LanguageUtils.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/LanguageUtils.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-QQ.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-QQ.js&action=raw&ctype=text/javascript'); //[[:w:Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js]] mw.loader.load('//ku.wikipedia.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/test.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/test.js&action=raw&ctype=text/javascript'); // This array of dependencies comes from [[MediaWiki:Gadgets-definition]]. // If the list of dependencies changes, copy the text after dependencies= // for TranslationAdder and run console.log(JSON.stringify("paste dependencies here".split(/, ?/))) // in your browser's JavaScript console. Put the resulting array as the first argument to mw.loader.using. //[[User:Wikihez/skrîpt/js/TranslationAdder.js]] //mw.loader.using(["ext.gadget.LegacyScriptsNewNode","mediawiki.cookie","mediawiki.util"], //function() { // importScript('User:Wikihez/skrîpt/js/TranslationAdder.js'); //}); mw.loader.load('https://en.wikipedia.org/w/index.php?title=User:BrandonXLF/TodoList.js&action=raw&ctype=text/javascript'); /* // [[:w:en:MediaWiki:Gadget-edittop.js]] mw.loader.load('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-edittop.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/addAutoCat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Balyozbot/Gadget-CommonWikt.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Balyozbot/Gadget-CommonWikt.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/hw-ceke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/hw-ceke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/sort-langheaders.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/sort-langheaders.js&action=raw&ctype=text/javascript'); //[[:en:User:Conrad.Irwin/Api.js]] mw.loader.load('//en.wiktionary.org/w/index.php?title=User:Conrad.Irwin/Api.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/etîket-çêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/etîket-çêke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/tagger.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/tagger.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-CatMaker.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-CatMaker.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/VisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/VisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/XMLize.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/XMLize.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/RhymesAdder.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/RhymesAdder.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Editor.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-aWa.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-aWa.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/FilterTranslations.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/FilterTranslations.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/custom.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/custom.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/reformat.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/reformat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/templateScript.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/templateScript.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/translateWiki.js]] ji aliyê [[Bikarhêner:Guherto]], [[Taybet:PermanentLink/4854098#Translatewiki.net]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/translateWiki.js&action=raw&ctype=text/javascript'); // Various fixes for the trees generated by [[Module:family tree]]. $(function () { // Show the top toggle. $('.familytree-toptoggle').css('display', ''); // Initialize the text of the toggles. $('.familytree').get().forEach(function (tree) { var isCollapsed = tree.classList.contains('mw-collapsed'); var toggles = $(tree).find('.familytree-toggle'); if (toggles[0]) { var customToggleClass = Array.prototype.filter.call(toggles[0].classList, function (className) { return className.indexOf('mw-customtoggle-familytree') === 0; })[0]; if (customToggleClass) { var toggledElement = $('#' + customToggleClass.replace('mw-customtoggle', 'mw-customcollapsible')); if (toggledElement) { toggles.html(toggledElement.data(isCollapsed ? 'expandtext' : 'collapsetext')); } } } }); // Change the text in the custom toggles generated by [[Module:family tree]] // when they are clicked. $('.mw-collapsible').on('beforeExpand.mw-collapsible beforeCollapse.mw-collapsible', function (event) { if (this.id.indexOf('mw-customcollapsible-familytree') === 0) { var toggle = $('.' + this.id.replace('mw-customcollapsible', 'mw-customtoggle')); if (event.type === 'beforeExpand') { toggle.html(this.dataset.collapsetext); } else { // beforeCollapse toggle.html(this.dataset.expandtext); } event.stopPropagation(); } }); }); */ mw.util.addPortletLink( mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions', '/w/index.php?title=' + mw.config.get('wgPageName') + '&action=edit&editintro=User:Wikihez/usenec', 'nec', 'id', 'use the New Entry Creator to create a new entry', 'a', 'nextnode'); omo5stzglcv11ou8fv3gm0kh8zz0rdx Bikarhêner:Wikihez/common.css 2 874440 6241612 6240772 2026-07-11T13:57:31Z Wikihez 7344 6241612 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 82ei9qvmndc9ngblbs55gtezizcvgap 6241619 6241612 2026-07-11T14:32:33Z Wikihez 7344 6241619 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } d2hteq2aayaj2mr1zeotu366nsrv3fq 6241623 6241619 2026-07-11T14:52:46Z Wikihez 7344 6241623 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(1em + 8px); min-height: calc(1em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } mfvo6cipm482zz4fu1j4ijzsbqv6786 6241625 6241623 2026-07-11T16:04:26Z Wikihez 7344 6241625 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(1em + 8px); min-height: calc(1em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktvi-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 9jtf2rmv57vb8lc27lydzrzrcr4htxn 6241626 6241625 2026-07-11T16:07:02Z Wikihez 7344 6241626 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(1em + 8px); min-height: calc(1em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktvi-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 56wz7yotposj045dgsadd01yp9c13i5 6241629 6241626 2026-07-11T16:10:17Z Wikihez 7344 6241629 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: auto; -webkit-overflow-scrolling: touch; } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktvi-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } tu1u9s1n7iqia2peonakt35l564dq76 6241630 6241629 2026-07-11T16:12:10Z Wikihez 7344 6241630 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktvi-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 1wbg1jjeeap7913ipsayga0kf9p8vum 6241631 6241630 2026-07-11T16:16:19Z Wikihez 7344 6241631 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktvi-start-form textarea.wiktvi-start-step-field, #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktvi-start-form textarea.wiktvi-start-narrow, #wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktvi-native-select-wrap { display: inline-block; position: relative; } .wiktvi-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktvi-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktvi-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktvi-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktvi-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktvi-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktvi-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktvi-dfn-label-toggle, a.wiktvi-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktvi-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktvi-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktvi-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktvi-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-tr, .wiktvi-dfn-nimune-sub textarea.wiktvi-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktvi-dfn-tpl-row { margin-bottom: 4px; } .wiktvi-dfn-tpl-select { font-size: 0.9em; } input.wiktvi-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktvi-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktvi-section-tabs .wiktvi-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 60qozyo1nrcrrxveadbk6hudw1kfxds 6241670 6241631 2026-07-11T20:51:08Z Wikihez 7344 6241670 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktku-dfn-label-toggle, a.wiktku-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktku-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } h1ntti3erck52md2cny9ea9yeogqb73 6241672 6241670 2026-07-11T21:11:41Z Wikihez 7344 6241672 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles =================================================================== */ /* Standard Input Theming using Palette */ #wiktku-start-form textarea, #wiktku-start-form input[type="text"], #wiktku-start-form input[type="search"], #wiktku-start-form select { background-color: var(--wikt-palette-white); color: var(--wikt-palette-black); border: 1px solid var(--wikt-palette-lightgrey); border-radius: 2px; padding: 4px; } /* Specific sizing for Etîmolojî and Bilêvkirin (Full Width) */ textarea.wiktku-pron-text, textarea.wiktku-etym-text { width: 100% !important; box-sizing: border-box !important; min-height: 100px; margin-top: 8px; display: block; } /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; width: 100%; /* Ensure full width on mobile */ } .wiktku-native-select-wrap input[type="search"] { display: block; width: 100%; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; left: 0; background: var(--wikt-palette-white); border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 100%; max-height: 14em; overflow-y: scroll; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; } ul.wiktku-ac-results li { padding: 8px 10px; cursor: pointer; font-size: 0.95em; min-height: 2.4em; display: flex; align-items: center; color: var(--wikt-palette-black); border-bottom: 1px solid var(--wikt-palette-lightergrey); } ul.wiktku-ac-results li:active, ul.wiktku-ac-results li:hover { background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); color: var(--wikt-palette-black); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-white); color: var(--wikt-palette-black); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Mane and Nimûne textareas ── */ textarea.wiktku-dfn-mane, textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields ── */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); } /* ── POS section tabs ── */ #wiktku-section-tabs .wiktku-section-tab { padding: 6px 12px; border: 1px solid var(--wikt-palette-lightgrey); border-radius: 4px 4px 0 0; background: var(--wikt-palette-dullcyan); color: var(--wikt-palette-black); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { background: var(--wikt-palette-white); border-bottom-color: transparent; font-weight: bold; } /* General Layout spacing */ .wiktku-start-step { margin-bottom: 20px; padding: 10px; border-bottom: 1px solid var(--wikt-palette-lightergrey); } imt0x9swdem082tmf3dszahbb0acoyv 6241673 6241672 2026-07-11T21:16:25Z Wikihez 7344 6241673 css text/css /* =================================================================== MediaWiki:Gadget-start.js — complete companion styles Mapped to MediaWiki:Gadget-Palette.css =================================================================== */ /* ── Global Step Field Styles ── */ #wiktku-start-form textarea, #wiktku-start-form input[type="text"], #wiktku-start-form input[type="search"], #wiktku-start-form select { background-color: var(--wikt-palette-white); color: var(--wikt-palette-black); border: 1px solid var(--wikt-palette-lightgrey); } /* ── Bilêvkirin & Etîmolojî: Full Width (Requested) ── */ textarea.wiktku-pron-text, textarea.wiktku-etym-text { width: 100% !important; box-sizing: border-box !important; min-height: 5em; /* Bigger height */ margin-top: 8px; display: block; resize: vertical !important; } /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; background: var(--wikt-palette-white); border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; min-height: 2.4em; display: flex; align-items: center; color: var(--wikt-palette-black); } ul.wiktku-ac-results li:active, ul.wiktku-ac-results li:hover { background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); color: var(--wikt-palette-black); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktku-dfn-label-toggle, a.wiktku-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; color: var(--wikt-palette-blue); /* Use palette blue for links */ } .wiktku-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane and Nimûne main textareas ── */ textarea.wiktku-dfn-mane, textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields ── */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); } /* ── Template selector row ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); color: var(--wikt-palette-black); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } /* Mobile Adjustments */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); font-size: 0.85em; } } 0mqwd99mozvcxcjbreg5mi9l3azkqpq 6241676 6241673 2026-07-11T21:22:01Z Wikihez 7344 Restored revision 6241670 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241676 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktku-dfn-label-toggle, a.wiktku-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktku-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } h1ntti3erck52md2cny9ea9yeogqb73 6241678 6241676 2026-07-11T21:35:40Z Wikihez 7344 6241678 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktku-dfn-label-toggle, a.wiktku-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktku-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: reduce indent and make sub-fields less wide to prevent overflow */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); /* viewport width minus margins/padding */ font-size: 0.85em; } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── Pronunciation (bilêvkirin) section ── */ .wiktku-pron-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-pron-wrap select.wiktku-tpl-insert-select { /* amber-1: warm parchment tint — visually links to "sound/speech" */ background: var(--wikt-palette-amber-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-pron-wrap textarea.wiktku-pron-text { width: 100%; box-sizing: border-box; /* amber-0: barely-there warm tint on the textarea itself */ background: var(--wikt-palette-amber-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* ── Etymology (etîmolojî) section ── */ .wiktku-etym-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-etym-wrap select.wiktku-tpl-insert-select { /* indigo-1: cool scholarly tint — "history / word origins" feel */ background: var(--wikt-palette-indigo-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-etym-wrap textarea.wiktku-etym-text { width: 100%; box-sizing: border-box; /* indigo-0: barely-there cool tint */ background: var(--wikt-palette-indigo-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* Mobile: ensure both sections stay readable at narrow widths */ @media (max-width: 720px) { .wiktku-pron-wrap textarea.wiktku-pron-text, .wiktku-etym-wrap textarea.wiktku-etym-text { font-size: 1em; /* don't shrink text on mobile */ height: calc(4 * 1.4em + 8px); /* 4 lines — more comfortable on small screens */ min-height: calc(4 * 1.4em + 8px); } .wiktku-pron-wrap select.wiktku-tpl-insert-select, .wiktku-etym-wrap select.wiktku-tpl-insert-select { font-size: 1em; min-height: 2.4em; /* match the touch-target size used elsewhere */ } } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } b4o944ziprxhdf74ktzsvkm22lox35f 6241679 6241678 2026-07-11T21:38:46Z Wikihez 7344 6241679 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels / lazy-reveal links ── */ a.wiktku-dfn-label-toggle, a.wiktku-dfn-lazy-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } .wiktku-dfn-lazy-links { margin: 2px 0 4px; line-height: 1.8; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: larger, easier-to-type fields for all dfn textareas */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } textarea.wiktku-dfn-mane, textarea.wiktku-dfn-nimune-text { font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── Pronunciation (bilêvkirin) section ── */ .wiktku-pron-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-pron-wrap select.wiktku-tpl-insert-select { /* amber-1: warm parchment tint — visually links to "sound/speech" */ background: var(--wikt-palette-amber-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-pron-wrap textarea.wiktku-pron-text { width: 100%; box-sizing: border-box; /* amber-0: barely-there warm tint on the textarea itself */ background: var(--wikt-palette-amber-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* ── Etymology (etîmolojî) section ── */ .wiktku-etym-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-etym-wrap select.wiktku-tpl-insert-select { /* indigo-1: cool scholarly tint — "history / word origins" feel */ background: var(--wikt-palette-indigo-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-etym-wrap textarea.wiktku-etym-text { width: 100%; box-sizing: border-box; /* indigo-0: barely-there cool tint */ background: var(--wikt-palette-indigo-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* Mobile: ensure both sections stay readable at narrow widths */ @media (max-width: 720px) { .wiktku-pron-wrap textarea.wiktku-pron-text, .wiktku-etym-wrap textarea.wiktku-etym-text { font-size: 1em; /* don't shrink text on mobile */ height: calc(4 * 1.4em + 8px); /* 4 lines — more comfortable on small screens */ min-height: calc(4 * 1.4em + 8px); } .wiktku-pron-wrap select.wiktku-tpl-insert-select, .wiktku-etym-wrap select.wiktku-tpl-insert-select { font-size: 1em; min-height: 2.4em; /* match the touch-target size used elsewhere */ } } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } p8tw17k4kqhjzo4qtro89phdaqxcoq3 6241726 6241679 2026-07-12T10:06:05Z Wikihez 7344 6241726 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels ── */ a.wiktku-dfn-label-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: larger, easier-to-type fields for all dfn textareas */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } textarea.wiktku-dfn-mane, textarea.wiktku-dfn-nimune-text { font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── Pronunciation (bilêvkirin) section ── */ .wiktku-pron-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-pron-wrap select.wiktku-tpl-insert-select { /* amber-1: warm parchment tint — visually links to "sound/speech" */ background: var(--wikt-palette-amber-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-pron-wrap textarea.wiktku-pron-text { width: 100%; box-sizing: border-box; /* amber-0: barely-there warm tint on the textarea itself */ background: var(--wikt-palette-amber-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* ── Etymology (etîmolojî) section ── */ .wiktku-etym-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-etym-wrap select.wiktku-tpl-insert-select { /* indigo-1: cool scholarly tint — "history / word origins" feel */ background: var(--wikt-palette-indigo-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-etym-wrap textarea.wiktku-etym-text { width: 100%; box-sizing: border-box; /* indigo-0: barely-there cool tint */ background: var(--wikt-palette-indigo-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* Mobile: ensure both sections stay readable at narrow widths */ @media (max-width: 720px) { .wiktku-pron-wrap textarea.wiktku-pron-text, .wiktku-etym-wrap textarea.wiktku-etym-text { font-size: 1em; /* don't shrink text on mobile */ height: calc(4 * 1.4em + 8px); /* 4 lines — more comfortable on small screens */ min-height: calc(4 * 1.4em + 8px); } .wiktku-pron-wrap select.wiktku-tpl-insert-select, .wiktku-etym-wrap select.wiktku-tpl-insert-select { font-size: 1em; min-height: 2.4em; /* match the touch-target size used elsewhere */ } } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } 94kazc7zg9lk45rgsvyc77ketgmp8d3 6241745 6241726 2026-07-12T11:44:29Z Wikihez 7344 6241745 css text/css /* =================================================================== MediaWiki:Gadget-start.js — companion styles Copy this file into MediaWiki:Common.css (or a dedicated gadget CSS page) so that the JS gadget no longer needs to inject styles at runtime. Requires MediaWiki:Gadget-Palette.css to be loaded for the --wikt-palette-* custom properties. =================================================================== */ /* Resizable textareas inside the wizard form */ #wiktku-start-form textarea.wiktku-start-step-field, #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield { resize: both !important; overflow: auto !important; box-sizing: border-box !important; vertical-align: top; } /* Narrow single-line textareas */ #wiktku-start-form textarea.wiktku-start-narrow, #wiktku-start-form textarea.wiktku-dfn-subfield.wiktku-start-narrow { width: 20em; min-width: 8em; height: calc(1em + 8px); min-height: calc(1em + 8px); padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; } /* ── Mobile autocomplete widget ── */ .wiktku-native-select-wrap { display: inline-block; position: relative; } .wiktku-native-select-wrap input[type="search"] { display: block; width: 20em; max-width: 100%; box-sizing: border-box; } ul.wiktku-ac-results { position: absolute; z-index: 9999; top: 100%; bottom: auto; left: 0; /* white in light mode, near-black in dark mode */ background: var(--wikt-palette-white); /* lightgrey border, recedes in dark mode */ border: 1px solid var(--wikt-palette-lightgrey); margin: 0; padding: 0; list-style: none; width: 20em; max-width: 90vw; max-height: 14em; overflow-y: scroll; /* scroll (not auto) ensures touch-scroll works on iOS/Android */ overscroll-behavior: contain; /* prevents page scroll bleeding through */ -webkit-overflow-scrolling: touch; /* legacy iOS momentum scrolling */ } ul.wiktku-ac-results li { padding: 6px 10px; cursor: pointer; font-size: 0.95em; /* larger touch target on mobile */ min-height: 2.4em; display: flex; align-items: center; } ul.wiktku-ac-results li:active { /* blue-9: vivid blue in light, readable bright blue in dark */ background: var(--wikt-palette-blue-9); color: var(--wikt-palette-white); } /* ── Wikitext preview panel ── */ #wiktku-preview-panel { margin-top: 1em; padding: 0.8em; /* paleblue: #f8f9fa light → #1c2229 dark (matches MediaWiki's surface tones) */ background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); white-space: pre-wrap; word-break: break-word; font-family: monospace; font-size: 0.9em; } /* ── Live rendered preview panel (desktop only) ── */ #wiktku-live-preview-panel { margin-top: 1em; padding: 0.8em; background: var(--wikt-palette-paleblue); border: 1px solid var(--wikt-palette-lightgrey); word-break: break-word; min-height: 2em; } /* ── Preview container (holds wikitext + live panels) ── */ #wiktku-preview-container { display: flex; flex-wrap: wrap; gap: 1em; margin-top: 0.5em; } /* ── Definition sense labels ── */ a.wiktku-dfn-label-toggle { display: inline-block; margin: 2px 4px 2px 0; font-size: 0.85em; } /* ── Mane textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-mane { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne main textarea: full width, 2-line start height ── */ textarea.wiktku-dfn-nimune-text { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); } /* ── Nimûne sub-fields (transliteration + translation) ── */ /* Indented wrapper with a left border to show these belong to the example above */ .wiktku-dfn-nimune-sub { margin-top: 3px; margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } /* Both sub-textareas: same starting size, full width of the indented column */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); min-width: 8em; padding-top: 2px !important; padding-bottom: 2px !important; line-height: 1.4 !important; font-size: 0.9em; } /* Subtle tint to distinguish tr from t at a glance */ .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr { background: var(--wikt-palette-cyan); /* pale cyan — transliteration */ } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { background: var(--wikt-palette-palegreen); /* pale green — translation */ } /* Mobile: larger, easier-to-type fields for all dfn textareas */ @media (max-width: 720px) { .wiktku-dfn-nimune-sub { margin-left: 0.5em; padding-left: 0.4em; } textarea.wiktku-dfn-mane, textarea.wiktku-dfn-nimune-text { font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-tr, .wiktku-dfn-nimune-sub textarea.wiktku-dfn-nimune-t { max-width: calc(100vw - 6em); font-size: 1em; height: calc(4 * 1.4em + 8px); min-height: calc(4 * 1.4em + 8px); } } /* ── Template selector row inside a sense block ── */ .wiktku-dfn-tpl-row { margin-bottom: 4px; } .wiktku-dfn-tpl-select { font-size: 0.9em; } input.wiktku-dfn-tpl-title { width: 20em; max-width: 100%; box-sizing: border-box; } /* ── Pronunciation (bilêvkirin) section ── */ .wiktku-pron-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-pron-wrap select.wiktku-tpl-insert-select { /* amber-1: warm parchment tint — visually links to "sound/speech" */ background: var(--wikt-palette-amber-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-pron-wrap textarea.wiktku-pron-text { width: 100%; box-sizing: border-box; /* amber-0: barely-there warm tint on the textarea itself */ background: var(--wikt-palette-amber-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* ── Etymology (etîmolojî) section ── */ .wiktku-etym-wrap { display: flex; flex-direction: column; gap: 4px; } .wiktku-etym-wrap select.wiktku-tpl-insert-select { /* indigo-1: cool scholarly tint — "history / word origins" feel */ background: var(--wikt-palette-indigo-1); border: 1px solid var(--wikt-palette-lightgrey); font-size: 0.9em; width: 100%; box-sizing: border-box; padding: 3px 4px; } .wiktku-etym-wrap textarea.wiktku-etym-text { width: 100%; box-sizing: border-box; /* indigo-0: barely-there cool tint */ background: var(--wikt-palette-indigo-0); height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } /* Mobile: ensure both sections stay readable at narrow widths */ @media (max-width: 720px) { .wiktku-pron-wrap textarea.wiktku-pron-text, .wiktku-etym-wrap textarea.wiktku-etym-text { font-size: 1em; /* don't shrink text on mobile */ height: calc(4 * 1.4em + 8px); /* 4 lines — more comfortable on small screens */ min-height: calc(4 * 1.4em + 8px); } .wiktku-pron-wrap select.wiktku-tpl-insert-select, .wiktku-etym-wrap select.wiktku-tpl-insert-select { font-size: 1em; min-height: 2.4em; /* match the touch-target size used elsewhere */ } } /* ── POS section tabs ── */ #wiktku-section-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 0.6em; } #wiktku-section-tabs .wiktku-section-tab { padding: 3px 10px; /* dullcyan: #eaecf0 light → #27292d dark (MediaWiki's standard inactive tab tone) */ border: 1px solid var(--wikt-palette-lightgrey); border-radius: 3px 3px 0 0; background: var(--wikt-palette-dullcyan); cursor: pointer; font-size: 0.9em; user-select: none; } #wiktku-section-tabs .wiktku-section-tab.wiktku-tab-active { /* white: full page background in light, deep near-black in dark */ background: var(--wikt-palette-white); border-bottom-color: var(--wikt-palette-white); font-weight: bold; } /* ── Quote / citation (jêder) block inside each nimûne item ── */ /* Toggle link — sits inline after the nimûne text/sub fields */ a.wiktku-dfn-quote-toggle { display: inline-block; margin-top: 4px; font-size: 0.85em; /* green-6: clear "add" affordance; readable in light and dark */ color: var(--wikt-palette-green-6); } /* The collapsible container */ .wiktku-dfn-quote-block { margin-top: 4px; margin-left: 1em; padding: 6px 8px; border-left: 3px solid var(--wikt-palette-amber-1); background: var(--wikt-palette-amber-0); display: flex; flex-direction: column; gap: 4px; } /* Main quote textarea */ .wiktku-dfn-quote-block textarea.wiktku-dfn-nimune-quote { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); background: var(--wikt-palette-amber-0); } /* Sub-fields for quote tr/t — same indented style as nimûne sub-fields */ .wiktku-dfn-quote-sub { margin-left: 1em; padding-left: 0.6em; border-left: 2px solid var(--wikt-palette-lightgrey); display: flex; flex-direction: column; gap: 3px; } .wiktku-dfn-quote-sub textarea.wiktku-dfn-nimune-quote-tr { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); background: var(--wikt-palette-cyan); } .wiktku-dfn-quote-sub textarea.wiktku-dfn-nimune-quote-t { width: 100%; box-sizing: border-box; height: calc(2 * 1.4em + 8px); min-height: calc(2 * 1.4em + 8px); background: var(--wikt-palette-palegreen); } /* Source template selector */ .wiktku-dfn-quote-src-sel { font-size: 0.9em; margin-top: 2px; } /* Dynamic source fields container */ .wiktku-dfn-quote-src-fields { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; } /* Each label+input row */ .wiktku-dfn-quote-src-row { display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; } .wiktku-dfn-quote-src-row label { font-size: 0.85em; white-space: nowrap; min-width: 8em; } input.wiktku-dfn-quote-src-input { flex: 1 1 12em; max-width: 100%; box-sizing: border-box; } /* Mobile: full-width quote block, slightly larger touch targets */ @media (max-width: 720px) { .wiktku-dfn-quote-block { margin-left: 0.3em; } .wiktku-dfn-quote-block textarea.wiktku-dfn-nimune-quote, .wiktku-dfn-quote-sub textarea.wiktku-dfn-nimune-quote-tr, .wiktku-dfn-quote-sub textarea.wiktku-dfn-nimune-quote-t { font-size: 1em; height: calc(3 * 1.4em + 8px); min-height: calc(3 * 1.4em + 8px); } .wiktku-dfn-quote-src-row label { min-width: 6em; } input.wiktku-dfn-quote-src-input { width: 100%; flex: 1 1 100%; } } jvmdwuh0fjb0y4qa7c3652cifjum5bu Bikarhêner:Wikihez/test.js 2 969083 6241610 6241601 2026-07-11T13:35:54Z Wikihez 7344 6241610 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Hemû qutiyên nivîsê û textareayan di forma xebatê de dikarin // bi kaşkirina kuncê rastê yê jêr mezin an biçûk bibin. mw.util.addCSS( "#wiktvi-start-form textarea.wiktvi-start-step-field," + "#wiktvi-start-form textarea.wiktvi-start-narrow," + "#wiktvi-start-form textarea.wiktvi-dfn-subfield {" + " resize: both !important;" + " overflow: auto !important;" + " box-sizing: border-box !important;" + " vertical-align: top;" + "}" + "#wiktvi-start-form textarea.wiktvi-start-narrow," + "#wiktvi-start-form textarea.wiktvi-dfn-subfield.wiktvi-start-narrow {" + " width: 20em;" + " min-width: 8em;" + " height: calc(1em + 8px);" + " min-height: calc(1em + 8px);" + " padding-top: 2px !important;" + " padding-bottom: 2px !important;" + " line-height: 1.4 !important;" + "}" + ".wiktvi-native-select-wrap { display: inline-block; position: relative; }" + ".wiktvi-native-select-wrap input[type='search'] {" + " display: block;" + " width: 20em;" + " max-width: 100%;" + " box-sizing: border-box;" + "}" + "ul.wiktvi-ac-results {" + " position: absolute;" + " z-index: 9999;" + " background: #fff;" + " border: 1px solid #a2a9b1;" + " margin: 0;" + " padding: 0;" + " list-style: none;" + " width: 20em;" + " max-width: 90vw;" + " max-height: 14em;" + " overflow-y: auto;" + " -webkit-overflow-scrolling: touch;" + "}" + "ul.wiktvi-ac-results li {" + " padding: 6px 10px;" + " cursor: pointer;" + " font-size: 0.95em;" + "}" + "ul.wiktvi-ac-results li:active {" + " background: #3366cc;" + " color: #fff;" + "}" + "#wiktvi-preview-panel {" + " margin-top: 1em;" + " padding: 0.8em;" + " background: #f8f9fa;" + " border: 1px solid #a2a9b1;" + " white-space: pre-wrap;" + " word-break: break-word;" + " font-family: monospace;" + " font-size: 0.9em;" + "}" + "a.wiktvi-dfn-label-toggle," + "a.wiktvi-dfn-lazy-toggle {" + " display: inline-block;" + " margin: 2px 4px 2px 0;" + " font-size: 0.85em;" + "}" + ".wiktvi-dfn-lazy-links {" + " margin: 2px 0 4px;" + " line-height: 1.8;" + "}" + ".wiktvi-dfn-tpl-row {" + " margin-bottom: 4px;" + "}" + ".wiktvi-dfn-tpl-select {" + " font-size: 0.9em;" + "}" + "input.wiktvi-dfn-tpl-title {" + " width: 20em;" + " max-width: 100%;" + " box-sizing: border-box;" + "}" + "#wiktvi-section-tabs {" + " display: flex;" + " flex-wrap: wrap;" + " gap: 4px;" + " margin-bottom: 0.6em;" + "}" + "#wiktvi-section-tabs .wiktvi-section-tab {" + " padding: 3px 10px;" + " border: 1px solid #a2a9b1;" + " border-radius: 3px 3px 0 0;" + " background: #eaecf0;" + " cursor: pointer;" + " font-size: 0.9em;" + " user-select: none;" + "}" + "#wiktvi-section-tabs .wiktvi-section-tab.wiktvi-tab-active {" + " background: #fff;" + " border-bottom-color: #fff;" + " font-weight: bold;" + "}" ); // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yek hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { tplSelect.append( $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") ); }); // Shows only options valid for the current lang; resets selection if // the currently chosen template is no longer valid. function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; tplSelect.find("option[value!='']").each(function () { var allowed = $(this).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; $(this).toggle(visible); if ($(this).val() === currentVal && visible) currentStillValid = true; }); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tpl = block.find("select.wiktvi-dfn-tpl-select").val() || ""; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit) var livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); var livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").css({ "margin-top": "1em", "padding": "0.8em", "background": "#f8f9fa", "border": "1px solid #a2a9b1", "word-break": "break-word", "min-height": "2em" }).hide(); // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>").css({ "display": "flex", "flex-wrap": "wrap", "gap": "1em", "margin-top": "0.5em" }); previewContainer.append(previewPanel).append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> cu7s9fdudlwa5wd9dw1kztritz7xnf1 6241611 6241610 2026-07-11T13:56:58Z Wikihez 7344 6241611 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yek hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { tplSelect.append( $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : "") ); }); // Shows only options valid for the current lang; resets selection if // the currently chosen template is no longer valid. function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; tplSelect.find("option[value!='']").each(function () { var allowed = $(this).attr("data-langs"); // allowed="" means no restriction (show for all langs). // .toggle() is unreliable on <option> elements in many browsers; // use the hidden property + disabled so the option is truly invisible // and cannot be selected programmatically when filtered out. var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; $(this).prop("hidden", !visible).prop("disabled", !visible); if ($(this).val() === currentVal && visible) currentStillValid = true; }); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit) var livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); var livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").css({ "margin-top": "1em", "padding": "0.8em", "background": "#f8f9fa", "border": "1px solid #a2a9b1", "word-break": "break-word", "min-height": "2em" }).hide(); // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>").css({ "display": "flex", "flex-wrap": "wrap", "gap": "1em", "margin-top": "0.5em" }); previewContainer.append(previewPanel).append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> hfrpfaez4ys0lpcpn3aoatb2rzjnwh2 6241614 6241611 2026-07-11T14:10:03Z Wikihez 7344 6241614 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yek hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit) var livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); var livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").css({ "margin-top": "1em", "padding": "0.8em", "background": "#f8f9fa", "border": "1px solid #a2a9b1", "word-break": "break-word", "min-height": "2em" }).hide(); // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>").css({ "display": "flex", "flex-wrap": "wrap", "gap": "1em", "margin-top": "0.5em" }); previewContainer.append(previewPanel).append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> jblpr1fubdzk51hgq4yaqqryr7gleda 6241615 6241614 2026-07-11T14:13:35Z Wikihez 7344 6241615 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yek hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit) var livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); var livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").css({ "margin-top": "1em", "padding": "0.8em", "background": "#f8f9fa", "border": "1px solid #a2a9b1", "word-break": "break-word", "min-height": "2em" }).hide(); // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>").css({ "display": "flex", "flex-wrap": "wrap", "gap": "1em", "margin-top": "0.5em" }); previewContainer.append(previewPanel).append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> r21b2g56qmgqq8t7ru0gzr8fcz0tysq 6241617 6241615 2026-07-11T14:29:35Z Wikihez 7344 6241617 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").css({ "margin-top": "1em", "padding": "0.8em", "background": "#f8f9fa", "border": "1px solid #a2a9b1", "word-break": "break-word", "min-height": "2em" }).hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>").css({ "display": "flex", "flex-wrap": "wrap", "gap": "1em", "margin-top": "0.5em" }); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> gj5zxbkvyzmsx8fqeyaw88odb6dbaj5 6241618 6241617 2026-07-11T14:30:46Z Wikihez 7344 6241618 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne * beşa wikînivîsê ya di bin tarîfekê de: an rêzikên "#: {{nm|...}}" * bo her nimûneyekê, an "#* {{bênimûne|lang}}" ger ti nimûne tinebe. * Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû * nivîsandin (bo dema tarîf heye û ne vala ye). */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (nimune) { return nimune !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (nimune) { if (nimune === "") return undefined; var bolded = nimune.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); return "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded) + "}}"; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — appended after the links row. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : "")); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readList("wiktvi-dfn-nimune"), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne is always visible. restoreSubList("wiktvi-dfn-nimune", sense.nimune); }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> tjhp82fqveuj03o1phgna4tf03f9t3h 6241620 6241618 2026-07-11T14:44:15Z Wikihez 7344 6241620 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercimey bo kurmancî (tenê ger ziman ne "ku" be) * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); if (n.t) tpl += "|t=" + escapeTemplateParam(n.t); } tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { // Grow the list when the last item's main field gets content. var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); if (needsTransliteration(lang)) { li.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { li.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { trTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); mainTa.after(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field — always after tr (or after mainTa if no tr) var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { tTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); li.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 2z4z81mxph28qk479vrahcqfpk0j20d 6241621 6241620 2026-07-11T14:48:21Z Wikihez 7344 6241621 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { // Grow the list when the last item's main field gets content. var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); if (needsTransliteration(lang)) { li.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { li.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { trTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); mainTa.after(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field — always after tr (or after mainTa if no tr) var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { tTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); li.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> dp3e5nai7fh7bghwf679u1hynuvjui6 6241622 6241621 2026-07-11T14:52:25Z Wikihez 7344 6241622 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> nwjted7r7jobiwfswhvu2a0pz7rdl37 6241624 6241622 2026-07-11T16:03:18Z Wikihez 7344 6241624 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 3) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 3b0a91ld6jfhnggzycpzro2f8sx5nsl 6241627 6241624 2026-07-11T16:07:17Z Wikihez 7344 6241627 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> kykahcpwcs3c899lev95xmqx4eyg0o1 6241628 6241627 2026-07-11T16:10:06Z Wikihez 7344 6241628 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> gig0hde23ydx1ec1ldk4y70ctwq2ct3 6241632 6241628 2026-07-11T16:16:32Z Wikihez 7344 6241632 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); li.on("mousedown touchstart", function (e) { // Use mousedown/touchstart (before blur) to register the pick. e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> lnn1xvsvsrhktyk3tjeuqdz9m8mb6h7 6241633 6241632 2026-07-11T16:19:54Z Wikihez 7344 6241633 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { var examples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var transExamples = { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade diin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }; var pos = values.pos ? values.pos.split("/")[0] : ""; return values.lang === "ku" ? (examples[pos] || "") : (transExamples[pos] || ""); }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { input.attr("placeholder", step.example(values) || ""); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 60eaq2x9ntpepcm7p959cox543lihcf 6241634 6241633 2026-07-11T16:25:03Z Wikihez 7344 6241634 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = values[id]; if (!words.join("").length) return ""; return "==== " + header + " ====\n" + $.map(words, function (word) { return word ? "* {{" + templateName + "|" + values.lang + "|" + escapeTemplateParam(word) + "}}" : undefined; }).join("\n") + "\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> d30oszfy6dsatdjvoqhbbcbcr734h24 6241636 6241634 2026-07-11T16:28:34Z Wikihez 7344 6241636 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "=== Bilêvkirin ===\n* {{ku-kîte}}\n\n"; } return ""; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", visible: function (values) { return false; }, output: function (values) { if (values.lang === "ku") { return "==== Etîmolojî ====\n{{ji?|ku}}"; } return ""; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 47qsteme4loll7mz11q5b7l8thz6o8a 6241637 6241636 2026-07-11T16:35:55Z Wikihez 7344 6241637 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", visible: function (values) { return values.lang && values.pos; }, multiple: true, rows: 2, output: function (values) { var lines = values.pron || []; var filled = $.grep(lines, function (line) { return $.trim(line) !== ""; }); if (!filled.length) return ""; return "=== Bilêvkirin ===\n" + $.map(filled, function (line) { return "* " + $.trim(line); }).join("\n") + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", visible: function (values) { return values.lang && values.pos; }, // Template definitions for etymology templates. etymTpls: [ { name: "(Bêyî şablon nivîse)", val: "" }, { name: "{{ji|…}}", val: "ji" }, { name: "{{qertaf|…}}", val: "qertaf" }, { name: "{{q|…}}", val: "q" }, { name: "{{hv|…}} (hevreh)", val: "hv" }, { name: "{{mîr|…}} (mîras)", val: "mîr" }, { name: "{{deyn|…}} (deyn)", val: "deyn" } ], build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-row").length) return null; var row = $("<div class='wiktvi-etym-row'></div>"); var tplSelect = $("<select class='wiktvi-etym-tpl-select wiktvi-start-narrow'></select>"); $.each(steps.etym.etymTpls, function (_, tpl) { tplSelect.append($("<option></option>").val(tpl.val).text(tpl.name)); }); var textArea = $("<textarea class='wiktvi-start-step-field wiktvi-etym-text'></textarea>") .attr("name", "wiktvi-etym-text-" + $.now()) .attr("rows", 2) .attr("placeholder", "Şablonê hilbijêre yan rasterast binivîse…"); row.append(tplSelect).append($("<br>")).append(textArea); stepDiv.append(row); return textArea; }, output: function (values) { var tpl = $("#wiktvi-start-etym .wiktvi-etym-tpl-select").val() || ""; var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; var content = ""; if (tpl === "ji") { // {{ji|sourcelangcode|currentlangcode|source word|tr=transcription|t=translation}} content = "{{ji|?|" + values.lang + "|" + escapeTemplateParam(text) + "}}"; } else if (tpl === "qertaf") { // {{qertaf|langcode|part1|part2}} content = "{{qertaf|" + values.lang + "|" + escapeTemplateParam(text) + "}}"; } else if (tpl === "q") { // {{q|langcode|page title}} content = "{{q|" + values.lang + "|" + escapeTemplateParam(text) + "}}"; } else if (tpl === "hv" || tpl === "mîr" || tpl === "deyn") { // {{hv|langcode|…}}, {{mîr|langcode|…}}, {{deyn|langcode|…}} content = "{{" + tpl + "|" + values.lang + "|" + escapeTemplateParam(text) + "}}"; } else { // Free-form — user writes the full markup themselves. content = text; } return "==== Etîmolojî ====\n" + content + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 3arw6biy0oplimp849y7ldx46q5zvq5 6241639 6241637 2026-07-11T16:43:51Z Wikihez 7344 6241639 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return values.lang && values.pos; }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — selecting inserts snippet at cursor. var sel = $("<select class='wiktvi-tpl-insert-select wiktvi-start-narrow'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — selecting inserts snippet at cursor. var sel = $("<select class='wiktvi-tpl-insert-select wiktvi-start-narrow'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) steps.pron.pronTpls = d.pronTpls; if (d.etymTpls) steps.etym.etymTpls = d.etymTpls; // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> n09vwen6oj3bur10yn50m8iao0o3bp2 6241640 6241639 2026-07-11T16:53:42Z Wikihez 7344 6241640 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { $.wiktviLinkify(text, callback); }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.pron, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "pron", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "pron") { snap.pron = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "pron") { // Remove existing wrap so build() recreates it (avoids guard blocking restore). $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); $("#wiktvi-start-pron .wiktvi-pron-text").val(snap.pron || ""); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); $.each(words, function (j, word) { var wordItems = lastRow.find("ul.wiktvi-trans-words li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } }); }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. var dfnSenses = steps.dfn.getSenses($("#wiktvi-start-dfn")); var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "pron") { $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> gauulk2mgfw9hnojzbnd2y3je9vfpjc 6241641 6241640 2026-07-11T17:08:17Z Wikihez 7344 6241641 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. var pos = values.pos ? values.pos.split("/")[0] : ""; return (steps.dfn.posExamples && steps.dfn.posExamples[pos]) || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row select.wiktvi-start-step-keyfield," + "li.wiktvi-trans-row .chosen-single").end() .find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.pron, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "pron", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "pron") { snap.pron = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "pron") { // Remove existing wrap so build() recreates it (avoids guard blocking restore). $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); $("#wiktvi-start-pron .wiktvi-pron-text").val(snap.pron || ""); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktvi-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { var exampleText = step.example(values) || ""; input.attr("placeholder", exampleText); // For the dfn step the mane textareas live inside sense blocks, // not directly as .wiktvi-start-step-field children of the step div. // Update them explicitly so all existing blocks get the right placeholder. if (step.id === "dfn") { stepDiv.find("textarea.wiktvi-dfn-mane").attr("placeholder", exampleText || "Mane…"); } } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { var label = steps.pos ? (sections[i].pos || ("Beş " + (i + 1))) : ("Beş " + (i + 1)); // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); // Update label of tab we're leaving with its pos. var leavingPos = sections[activeSection].pos || ""; activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "pron") { $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> bocsypg33fuo9q3cps1ddiy4k4kd17t 6241642 6241641 2026-07-11T17:33:32Z Wikihez 7344 6241642 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.pron, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "pron", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "pron") { snap.pron = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "pron") { // Remove existing wrap so build() recreates it (avoids guard blocking restore). $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); $("#wiktvi-start-pron .wiktvi-pron-text").val(snap.pron || ""); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktvi-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "pron") { $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. var pinnedCodes = ["ku", "zza", "ckb", "sdh", "de", "ar", "fa", "fr", "fi", "en", "sv", "tr"]; var pinnedChoices = steps.lang.choices.slice(); // copy of the initial 9 new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> es8ppdu6h4v38fr1n9mmxz095ov9ful 6241652 6241642 2026-07-11T19:04:31Z Wikihez 7344 6241652 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.pron, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "pron", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "pron") { snap.pron = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "pron") { // Remove existing wrap so build() recreates it (avoids guard blocking restore). $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); $("#wiktvi-start-pron .wiktvi-pron-text").val(snap.pron || ""); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktvi-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "pron") { $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> pzy10cfd1t4i34jis2do7u7d67r6r8d 6241653 6241652 2026-07-11T19:33:29Z Wikihez 7344 6241653 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "pron", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "pron") { snap.pron = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "pron") { // Remove existing wrap so build() recreates it (avoids guard blocking restore). $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); $("#wiktvi-start-pron .wiktvi-pron-text").val(snap.pron || ""); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktvi-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "pron") { $("#wiktvi-start-pron .wiktvi-pron-wrap").remove(); steps.pron.build($("#wiktvi-start-pron")); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> esjk0svgpui2vlzhocqbvd49bo5dz0u 6241654 6241653 2026-07-11T19:38:03Z Wikihez 7344 6241654 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktviCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktvi-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktvi-start-narrow wiktvi-ac-input"); var resultsList = $("<ul class='wiktvi-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-pron .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-pron-wrap").length) return null; var wrap = $("<div class='wiktvi-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-pron-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-pron .wiktvi-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktvi-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktvi-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktvi-start-step-field wiktvi-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktvi-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktvi-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktvi-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktvi-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktvi-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktvi-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktvi-dfn-subfield" + (narrow ? " wiktvi-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktvi-dfn-list").length) return null; var list = $("<ol class='wiktvi-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktvi-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktvi-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktvi-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktvi-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktvi-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktvi-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktvi-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktvi-dfn-herwiha"), hevmane: readList("wiktvi-dfn-hevmane"), dijmane: readList("wiktvi-dfn-dijmane"), koordine: readList("wiktvi-dfn-koordine"), jornav: readList("wiktvi-dfn-jornav"), jernav: readList("wiktvi-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktvi-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktvi-start-etym .wiktvi-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktvi-etym-wrap").length) return null; var wrap = $("<div class='wiktvi-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktvi-etym-" + $.now()) .attr("class", "wiktvi-start-step-field wiktvi-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktvi-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktvi-start-dfn li.wiktvi-dfn-sense").each(function () { if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktvi-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktvi-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktvi-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktvi-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktvi-trans-list"); var isLast = row.is(list.children("li.wiktvi-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktvi-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktvi-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktvi-trans-list").length) return null; var list = $("<ul class='wiktvi-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktvi-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktvi-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktvi-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktvi-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktvi-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktvi-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktvi-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktvi-dfn-sense").last(); } // Template selector. block.find("select.wiktvi-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktvi-dfn-mane").hide(); block.find("input.wiktvi-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktvi-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktvi-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktvi-dfn-", "").toLowerCase(); block.find("a.wiktvi-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktvi-dfn-etiket": sense.etiket, "wiktvi-dfn-herwiha": sense.herwiha, "wiktvi-dfn-hevmane": sense.hevmane, "wiktvi-dfn-dijmane": sense.dijmane, "wiktvi-dfn-koordine": sense.koordine, "wiktvi-dfn-jornav": sense.jornav, "wiktvi-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktvi-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktvi-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktvi-dfn-nimune-li'></li>"); li.find(".wiktvi-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktvi-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktvi-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktvi-start-etym .wiktvi-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktvi-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); $("#wiktvi-start-etym .wiktvi-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktvi-trans-list"); var lastRow = list.find("li.wiktvi-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktvi-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktvi-start-" + id); var fields = stepDiv.find(".wiktvi-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktvi-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktvi-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktvi-start-" + step.id + " .wiktvi-start-step-keyfield").not(this); var oldValue = $(this).data("wiktvi-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktvi-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktvi-start-dfn .wiktvi-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktvi-start-dfn .wiktvi-dfn-nimune-list li.wiktvi-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktvi-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktvi-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktvi-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktvi-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktvi-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktvi-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktvi-dfn-subfield wiktvi-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktvi-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktvi-start-" + stepId).slideUp(); // $("#wiktvi-start-" + stepId + " .wiktvi-start-step-field").val(""); } else { var stepDiv = $("#wiktvi-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktvi-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktvi-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktvi-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktvi-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktvi-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktvi-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktvi-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktvi-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktvi-start-step", id: "wiktvi-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktvi-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktvi-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktvi-start-step-question", "for": "wiktvi-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktvi-start-step-field", id: "wiktvi-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktvi-start-step-field") .attr("id", "wiktvi-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktvi-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktvi-section-tab") .text(tabLabel) .toggleClass("wiktvi-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktvi-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktvi-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktvi-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktvi-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktvi-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktvi-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktvi-start-dfn"); stepDiv.find("ol.wiktvi-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktvi-start-etym .wiktvi-etym-wrap").remove(); steps.etym.build($("#wiktvi-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktvi-start-trans"); transDiv.find("ul.wiktvi-trans-list").remove(); return; } var stepDiv = $("#wiktvi-start-" + id); stepDiv.find(".wiktvi-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktvi-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>"); var previewLabel = $("<label for='wiktvi-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktvi-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktvi-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktvi-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktvi-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktvi-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktvi-start-trans .wiktvi-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 60ouamomr912uxqca2orckhinht7ipf 6241669 6241654 2026-07-11T20:50:24Z Wikihez 7344 6241669 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 7jpexgd435ch6lxa75c3hll2oacskc3 6241671 6241669 2026-07-11T21:11:39Z Wikihez 7344 6241671 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") // Ensure wiktku-pron-text is here .attr("rows", 4) // Increased rows for better visibility .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> b4qn6mvsgl4x0quf5zxtsehsz0k5r5d 6241674 6241671 2026-07-11T21:20:39Z Wikihez 7344 6241674 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") // Ensure wiktku-pron-text is here .attr("rows", 4) // Increased rows for better visibility .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 5) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 4) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 4) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 4) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 4) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 35eml7pmd9kalqlh39r4edm6sygv0bz 6241675 6241674 2026-07-11T21:21:54Z Wikihez 7344 Restored revision 6241669 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241675 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 2) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 3) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 1); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 7jpexgd435ch6lxa75c3hll2oacskc3 6241677 6241675 2026-07-11T21:27:30Z Wikihez 7344 6241677 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. function escapeTemplateParam(str) { if (typeof str !== "string") return str; return str.replace(/\|/g, "{{!}}").replace(/=/g, "{{=}}"); } var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + escapeTemplateParam(bolded); if (typeof n === "object") { if (n.tr) tpl += "|tr=" + escapeTemplateParam(n.tr); // Translation as third positional param (no key needed). if (n.t) tpl += "|" + escapeTemplateParam(n.t); } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + escapeTemplateParam(words[0]) + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + escapeTemplateParam(w); }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + escapeTemplateParam(values.tr); } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return escapeTemplateParam($.trim(part)); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1].map(escapeTemplateParam); var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 586di65wbicqf7zp9xouw4dbic18fr4 6241680 6241677 2026-07-11T21:44:53Z Wikihez 7344 6241680 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the group hasn't been revealed yet, click its link. if (!groupDiv.length) { var needle = cls.replace("wiktku-dfn-", "").toLowerCase(); block.find("a.wiktku-dfn-lazy-toggle").filter(function () { return $(this).text().toLowerCase().indexOf(needle) !== -1; }).trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> hx04g5brwe3dtwmqcgmtu4vup2p9ldu 6241724 6241680 2026-07-12T09:19:01Z Wikihez 7344 6241724 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = $("<div></div>").addClass("wiktku-dfn-lazy-links"); block.append(lazyLinksDiv); // — Sub-field groups — // nimûne: always visible (inserted after the links row). // etîket + herwiha/hevmane/dijmane/koordine/jornav/jernav: lazy (click-to-add). var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false, lazy: false }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true, lazy: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true, lazy: true } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (!g.lazy) { // Always-visible group (Nimûne) — each item is a compound widget. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); /** * Build one nimûne <li>: a main textarea, and — depending on * the currently selected language — optional tr/t sub-fields. * tr (transliteration) shown when needsTransliteration(lang) * t (translation to ku) shown when lang !== "ku" * The sub-fields are appended inline after the main textarea. */ function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); // Sub-fields (tr, t) sit in an indented wrapper beneath the main textarea. var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } // Store the builder so refresh() can call it when lang changes. groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Lazy group — link lives in lazyLinksDiv; group is built on click. var addLink = $("<a href='#'></a>") .addClass("wiktku-dfn-lazy-toggle") .attr("data-cls", g.cls) .text("(+ " + g.label + ")"); addLink.on("click", function (evt) { evt.preventDefault(); addLink.remove(); var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); // Insert before Nimûne (the last fixed group) to preserve declaration order. block.find(".wiktku-dfn-nimune-group").before(groupDiv); firstInput.focus(); }); lazyLinksDiv.append(addLink).append(" "); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Nimûne lines. out += formatNimune(sense.nimune, lang); // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, nimune, herwiha …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); // If the lazy group hasn't been revealed yet, trigger its link. // Match by data-cls attribute (reliable) instead of label text // (which contains Kurdish characters like î that break indexOf). if (!groupDiv.find("ol, ul").length) { block.find("a.wiktku-dfn-lazy-toggle[data-cls='" + cls + "']").trigger("click"); groupDiv = block.find("." + cls + "-group"); } var subList = groupDiv.find("ol, ul").first(); // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 4rnhizv368ncoi8it0fc9eyv3g3j3b1 6241725 6241724 2026-07-12T10:05:40Z Wikihez 7344 6241725 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> emqslj3nf3deyn7iw3lc7khzfgkvkkl 6241730 6241725 2026-07-12T10:15:59Z Wikihez 7344 6241730 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.pron.pronTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> smrmmhttpsss0tcwp46ihkfg0l8zt0p 6241731 6241730 2026-07-12T10:26:41Z Wikihez 7344 6241731 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", c: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> qdwa5xcl76eoubnfhj0xqvnwdjdthev 6241734 6241731 2026-07-12T10:33:04Z Wikihez 7344 6241734 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc)); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> s1ska67wnfipehj65nz4gqx9ngaongx 6241735 6241734 2026-07-12T10:38:33Z Wikihez 7344 6241735 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — options populated/refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> iv36j6nl0fm7sieurmztt033i1j7jdc 6241736 6241735 2026-07-12T10:41:00Z Wikihez 7344 6241736 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — populated via refreshTplSelect() below. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); // Populate options now that the select is in the DOM. steps.pron.refreshTplSelect(); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — populated via refreshTplSelect() below. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); // Populate options now that the select is in the DOM. steps.etym.refreshTplSelect(); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> odbs28rnstm14sfz19kk2d0pax4ef5t 6241737 6241736 2026-07-12T10:44:57Z Wikihez 7344 6241737 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); // Populate options directly here using the same filter logic. var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); // Populate options directly here. var lang = getValues().lang || ""; $.each(steps.etym.etymTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 5qr11us3d33q08m086qq0l0ou9fkufs 6241739 6241737 2026-07-12T10:51:58Z Wikihez 7344 6241739 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); // Populate options directly here using the same filter logic. var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); // Populate options directly here. var lang = getValues().lang || ""; $.each(steps.etym.etymTpls, function (_, tpl) { var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns only when language changes. var refreshLang = values.lang || ""; if (refreshLang !== refresh._lastLang) { refresh._lastLang = refreshLang; steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); } // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 8kwapt7ll4190juhv3tahpzg8wqww9q 6241740 6241739 2026-07-12T10:53:13Z Wikihez 7344 6241740 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); } }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> qot6wyde5hvwqz6ymg1yb5ozbwfmab5 6241742 6241740 2026-07-12T11:17:28Z Wikihez 7344 6241742 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. if (text.length < 200) tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (!text) return ""; return "==== Etîmolojî ====\n" + text + "\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.binereherwiha, steps.etym, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "binereherwiha", "etym", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.binereherwiha.output(values); entry += steps.etym.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 7txm5bpcwjuof23lb50fd0oe79wd2fw 6241743 6241742 2026-07-12T11:27:27Z Wikihez 7344 6241743 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin. * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. // rêz=1 is not used for ku — definitions are shown on separate lines there. if (text.length < 200 && lang !== "ku") tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (text) { return "==== Etîmolojî ====\n" + text + "\n\n"; } // No etymology entered — emit {{ji?|lang}} as a placeholder, // but only when the entry has at least one regular mane sense // (not a template sense like {{guharto|…}}). var hasRegularMane = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { var tpl = $(this).find("select.wiktku-dfn-tpl-select").val(); var mane = $.trim($(this).find("textarea.wiktku-dfn-mane").val()); if (!tpl && mane) { hasRegularMane = true; return false; // break } }); if (!hasRegularMane) return ""; return "==== Etîmolojî ====\n{{ji?|" + values.lang + "}}\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.etym, steps.binereherwiha, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "etym", "binereherwiha", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.etym.output(values); entry += steps.binereherwiha.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 4rtr2svsipjrxqb2ieh30bqzq8v2kq4 6241744 6241743 2026-07-12T11:43:59Z Wikihez 7344 6241744 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t, quote, quoteTr, quoteT, * jêderTpl, jêderFields } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * quote — jêgirtina çavkaniyê * quoteTr — transkrîpsiyona jêgirtinê * quoteT — tercimeya jêgirtinê * jêderTpl — navê şablona jêderê (jêder-kitêb/kovar/malper) * jêderFields — { key: value, … } parametreyên şablonê * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin (ne ji bo ku). * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. // rêz=1 is not used for ku — definitions are shown on separate lines there. if (text.length < 200 && lang !== "ku") tpl += "|rêz=1"; tpl += "}}"; // — Quote / citation block — if (typeof n === "object" && n.quote) { // #* quote line (bold the page name like the example line) var boldedQ = n.quote.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var quoteLine = "\n#* " + boldedQ; if (n.quoteTr) quoteLine += "\n#*: '''" + n.quoteTr + "'''"; if (n.quoteT) quoteLine += "\n#*: " + n.quoteT; tpl += quoteLine; // #** citation template line if (n.jêderTpl) { var cite = "\n#** {{" + n.jêderTpl + "|" + lang; cite += "|jêgirtin=" + n.quote; if (n.quoteTr) cite += "|tr=" + n.quoteTr; if (n.quoteT) cite += "|tercime=" + n.quoteT; var fields = n.jêderFields || {}; $.each(fields, function (key, val) { if (val) cite += "|" + key + "=" + val; }); cite += "}}"; tpl += cite; } } return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); // — Quote / citation block — var quoteBlock = $("<div></div>").addClass("wiktku-dfn-quote-block").hide(); // Quote text textarea var quoteTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote") .attr("placeholder", "Jêgirtin…"); var quoteSubWrap = $("<div></div>").addClass("wiktku-dfn-quote-sub"); if (needsTransliteration(lang)) { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-tr") .attr("placeholder", "Transkrîpsiyona jêgirtinê…") ); } if (lang && lang !== "ku") { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-t") .attr("placeholder", "Tercimeya jêgirtinê (kurmancî)…") ); } // Source template selector var srcSel = $("<select></select>") .addClass("wiktku-dfn-quote-src-sel"); srcSel.append($("<option value=''>— Çavkaniyê hilbijêre —</option>")); var jêderDefs = steps.dfn.jêderDefs || {}; $.each(jêderDefs, function (tplName, def) { srcSel.append($("<option></option>").val(tplName).text(def.label)); }); // Dynamic source fields container var srcFields = $("<div></div>").addClass("wiktku-dfn-quote-src-fields"); srcSel.on("change", function () { srcFields.empty(); var chosen = $(this).val(); if (!chosen) return; var def = (steps.dfn.jêderDefs || {})[chosen]; if (!def) return; $.each(def.fields, function (_, f) { var row = $("<div></div>").addClass("wiktku-dfn-quote-src-row"); var lbl = $("<label></label>").text(f.label + ": "); var inp = $("<input type='text'>") .addClass("wiktku-dfn-quote-src-input wiktku-start-narrow") .attr("data-field-key", f.key) .attr("placeholder", f.label + "…"); row.append(lbl).append(inp); srcFields.append(row); }); }); quoteBlock.append(quoteTa); if (quoteSubWrap.children().length) quoteBlock.append(quoteSubWrap); quoteBlock.append(srcSel).append(srcFields); // Toggle link var quoteToggle = $("<a></a>") .addClass("wiktku-dfn-quote-toggle") .attr("href", "#") .text("+ Jêder zêde bike"); quoteToggle.on("click", function (e) { e.preventDefault(); if (quoteBlock.is(":hidden")) { quoteBlock.show(); $(this).text("− Jêderê rake"); quoteTa.focus(); } else { quoteBlock.hide(); $(this).text("+ Jêder zêde bike"); // Clear all quote fields when hidden quoteBlock.find("textarea, input[type='text']").val(""); srcSel.val(""); srcFields.empty(); } }); li.append(quoteToggle).append(quoteBlock); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, // Populated from MediaWiki:Gadget-start.js/data.json (jêderDefs). jêderDefs: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t?, quote?, quoteTr?, quoteT?, jêderTpl?, jêderFields? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; // Quote / citation data — only if the block is visible and has content. var quoteBlock = $(this).find(".wiktku-dfn-quote-block"); if (quoteBlock.is(":visible")) { var quote = $.trim($(this).find(".wiktku-dfn-nimune-quote").val()); if (quote) { obj.quote = quote; var qtr = $.trim($(this).find(".wiktku-dfn-nimune-quote-tr").val()); var qt = $.trim($(this).find(".wiktku-dfn-nimune-quote-t").val()); if (qtr) obj.quoteTr = qtr; if (qt) obj.quoteT = qt; var jêderTpl = $(this).find(".wiktku-dfn-quote-src-sel").val(); if (jêderTpl) { obj.jêderTpl = jêderTpl; var fields = {}; $(this).find(".wiktku-dfn-quote-src-input").each(function () { var k = $(this).attr("data-field-key"); var v = $.trim($(this).val()); if (k && v) fields[k] = v; }); obj.jêderFields = fields; } } } items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (text) { return "==== Etîmolojî ====\n" + text + "\n\n"; } // No etymology entered — emit {{ji?|lang}} as a placeholder, // but only when the entry has at least one regular mane sense // (not a template sense like {{guharto|…}}). var hasRegularMane = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { var tpl = $(this).find("select.wiktku-dfn-tpl-select").val(); var mane = $.trim($(this).find("textarea.wiktku-dfn-mane").val()); if (!tpl && mane) { hasRegularMane = true; return false; // break } }); if (!hasRegularMane) return ""; return "==== Etîmolojî ====\n{{ji?|" + values.lang + "}}\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.etym, steps.binereherwiha, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "etym", "binereherwiha", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t?, quote?, … } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); // Restore quote / citation data. if (typeof n === "object" && n.quote) { var quoteBlock = li.find(".wiktku-dfn-quote-block"); var quoteToggle = li.find(".wiktku-dfn-quote-toggle"); quoteBlock.show(); quoteToggle.text("− Jêderê rake"); li.find(".wiktku-dfn-nimune-quote").val(n.quote); if (n.quoteTr) li.find(".wiktku-dfn-nimune-quote-tr").val(n.quoteTr); if (n.quoteT) li.find(".wiktku-dfn-nimune-quote-t").val(n.quoteT); if (n.jêderTpl) { var srcSel = li.find(".wiktku-dfn-quote-src-sel"); srcSel.val(n.jêderTpl).trigger("change"); // Fill in the source field inputs after the change event renders them. if (n.jêderFields) { $.each(n.jêderFields, function (key, val) { li.find(".wiktku-dfn-quote-src-input[data-field-key='" + key + "']").val(val); }); } } } nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.etym.output(values); entry += steps.binereherwiha.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate citation template definitions for the quote widget. if (d.jêderDefs) steps.dfn.jêderDefs = d.jêderDefs; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> l02skb2a7qjxjhwzxdth1ki5mfl9yb1 6241746 6241744 2026-07-12T11:48:34Z Wikihez 7344 6241746 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t, quote, quoteTr, quoteT, * jêderTpl, jêderFields } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * quote — jêgirtina çavkaniyê * quoteTr — transkrîpsiyona jêgirtinê * quoteT — tercimeya jêgirtinê * jêderTpl — navê şablona jêderê (jêder-kitêb/kovar/malper) * jêderFields — { key: value, … } parametreyên şablonê * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin (ne ji bo ku). * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. // rêz=1 is not used for ku — definitions are shown on separate lines there. if (text.length < 200 && lang !== "ku") tpl += "|rêz=1"; tpl += "}}"; // — Quote / citation block — if (typeof n === "object" && n.quote) { // #* quote line (bold the page name like the example line) var boldedQ = n.quote.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var quoteLine = "\n#* " + boldedQ; if (n.quoteTr) quoteLine += "\n#*: '''" + n.quoteTr + "'''"; if (n.quoteT) quoteLine += "\n#*: " + n.quoteT; tpl += quoteLine; // #** citation template line if (n.jêderTpl) { var cite = "\n#** {{" + n.jêderTpl + "|" + lang; cite += "|jêgirtin=" + n.quote; if (n.quoteTr) cite += "|tr=" + n.quoteTr; if (n.quoteT) cite += "|tercime=" + n.quoteT; var fields = n.jêderFields || {}; $.each(fields, function (key, val) { if (val) cite += "|" + key + "=" + val; }); cite += "}}"; tpl += cite; } } return tpl; }).join(""); } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); // — Quote / citation block — var quoteBlock = $("<div></div>").addClass("wiktku-dfn-quote-block").hide(); // Quote text textarea var quoteTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote") .attr("placeholder", "Jêgirtin…"); var quoteSubWrap = $("<div></div>").addClass("wiktku-dfn-quote-sub"); if (needsTransliteration(lang)) { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-tr") .attr("placeholder", "Transkrîpsiyona jêgirtinê…") ); } if (lang && lang !== "ku") { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-t") .attr("placeholder", "Tercimeya jêgirtinê (kurmancî)…") ); } // Source template selector var srcSel = $("<select></select>") .addClass("wiktku-dfn-quote-src-sel"); srcSel.append($("<option value=''>— Çavkaniyê hilbijêre —</option>")); var jêderDefs = steps.dfn.jederDefs || {}; $.each(jêderDefs, function (tplName, def) { srcSel.append($("<option></option>").val(tplName).text(def.label)); }); // Dynamic source fields container var srcFields = $("<div></div>").addClass("wiktku-dfn-quote-src-fields"); srcSel.on("change", function () { srcFields.empty(); var chosen = $(this).val(); if (!chosen) return; var def = (steps.dfn.jederDefs || {})[chosen]; if (!def) return; $.each(def.fields, function (_, f) { var row = $("<div></div>").addClass("wiktku-dfn-quote-src-row"); var lbl = $("<label></label>").text(f.label + ": "); var inp = $("<input type='text'>") .addClass("wiktku-dfn-quote-src-input wiktku-start-narrow") .attr("data-field-key", f.key) .attr("placeholder", f.label + "…"); row.append(lbl).append(inp); srcFields.append(row); }); }); quoteBlock.append(quoteTa); if (quoteSubWrap.children().length) quoteBlock.append(quoteSubWrap); quoteBlock.append(srcSel).append(srcFields); // Toggle link var quoteToggle = $("<a></a>") .addClass("wiktku-dfn-quote-toggle") .attr("href", "#") .text("+ Jêder zêde bike"); quoteToggle.on("click", function (e) { e.preventDefault(); if (quoteBlock.is(":hidden")) { quoteBlock.show(); $(this).text("− Jêderê rake"); quoteTa.focus(); } else { quoteBlock.hide(); $(this).text("+ Jêder zêde bike"); // Clear all quote fields when hidden quoteBlock.find("textarea, input[type='text']").val(""); srcSel.val(""); srcFields.empty(); } }); li.append(quoteToggle).append(quoteBlock); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, // Populated from MediaWiki:Gadget-start.js/data.json (jederDefs). jederDefs: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t?, quote?, quoteTr?, quoteT?, jêderTpl?, jêderFields? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; // Quote / citation data — only if the block is visible and has content. var quoteBlock = $(this).find(".wiktku-dfn-quote-block"); if (quoteBlock.is(":visible")) { var quote = $.trim($(this).find(".wiktku-dfn-nimune-quote").val()); if (quote) { obj.quote = quote; var qtr = $.trim($(this).find(".wiktku-dfn-nimune-quote-tr").val()); var qt = $.trim($(this).find(".wiktku-dfn-nimune-quote-t").val()); if (qtr) obj.quoteTr = qtr; if (qt) obj.quoteT = qt; var jêderTpl = $(this).find(".wiktku-dfn-quote-src-sel").val(); if (jêderTpl) { obj.jêderTpl = jêderTpl; var fields = {}; $(this).find(".wiktku-dfn-quote-src-input").each(function () { var k = $(this).attr("data-field-key"); var v = $.trim($(this).val()); if (k && v) fields[k] = v; }); obj.jêderFields = fields; } } } items.push(obj); }); return items; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (text) { return "==== Etîmolojî ====\n" + text + "\n\n"; } // No etymology entered — emit {{ji?|lang}} as a placeholder, // but only when the entry has at least one regular mane sense // (not a template sense like {{guharto|…}}). var hasRegularMane = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { var tpl = $(this).find("select.wiktku-dfn-tpl-select").val(); var mane = $.trim($(this).find("textarea.wiktku-dfn-mane").val()); if (!tpl && mane) { hasRegularMane = true; return false; // break } }); if (!hasRegularMane) return ""; return "==== Etîmolojî ====\n{{ji?|" + values.lang + "}}\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.etym, steps.binereherwiha, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "etym", "binereherwiha", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t?, quote?, … } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); // Restore quote / citation data. if (typeof n === "object" && n.quote) { var quoteBlock = li.find(".wiktku-dfn-quote-block"); var quoteToggle = li.find(".wiktku-dfn-quote-toggle"); quoteBlock.show(); quoteToggle.text("− Jêderê rake"); li.find(".wiktku-dfn-nimune-quote").val(n.quote); if (n.quoteTr) li.find(".wiktku-dfn-nimune-quote-tr").val(n.quoteTr); if (n.quoteT) li.find(".wiktku-dfn-nimune-quote-t").val(n.quoteT); if (n.jêderTpl) { var srcSel = li.find(".wiktku-dfn-quote-src-sel"); srcSel.val(n.jêderTpl).trigger("change"); // Fill in the source field inputs after the change event renders them. if (n.jêderFields) { $.each(n.jêderFields, function (key, val) { li.find(".wiktku-dfn-quote-src-input[data-field-key='" + key + "']").val(val); }); } } } nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.etym.output(values); entry += steps.binereherwiha.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate citation template definitions for the quote widget. if (d.jederDefs) steps.dfn.jederDefs = d.jederDefs; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> hk1g2jftdl51pp6jdavv715keb3mvmu 6241752 6241746 2026-07-12T11:57:36Z Wikihez 7344 6241752 javascript text/javascript // Çavkanî [[vi:MediaWiki:Gadget-start.js]] //<nowiki> $(function () { var ns = mw.config.get("wgNamespaceNumber"); if (ns && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } var action = mw.config.get("wgAction"); if (!(action === "edit" || action === "submit") || !$(".mw-newarticletext, .mw-newarticletextanon").length) { return; } if (window.location.href.includes("editintro=User:Wikihez/creation/intro")) { return; // Do not run the script wextê WF:Bilez dişuxile } // Herfa ewil a kelîmeyê dike mezin. Fonksiyoneke sade li şûna // String.prototype.wiktkuCapitalize, daku prototypeya bingehîn neyê // gemarîkirin, û bi ewletir e (rasterast li ser rêzikên vala kar dike). function capitalize(str) { if (!str) return str; return str[0].toUpperCase() + str.substr(1); } // Karakterên xisûsî ên RegExp-ê direvîne, daku nivîsa dînamîk (wek navê // rûpelê) bi ewletî bikeve nav `new RegExp(...)`. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } /** * Nivîsek li cihê kursora texareayek dixin. * Piştî xistinê kursor li dawiya nivîsa xistî tê danîn. */ function insertAtCursor(el, text) { var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); var pos = start + text.length; el.selectionStart = el.selectionEnd = pos; } // Karakterên ku maneyeke xisûsî di parametreyên şablonan de hene ("|" ji // hev cuda dike, "=" dibe ku wek nav=nirx were şirovekirin) direvîne, // daku nivîsa vekirî ya bikarhêner şablonê neşikîne. // NOTE: escapeTemplateParam is intentionally not applied — users may freely // include | and = to add extra template parameters themselves. var pageName = mw.config.get("wgPageName").replace(/_/g, " "); if (ns) pageName = pageName.replace(/.*\//, ""); var pageNameRe = escapeRegExp(pageName); var userLang = mw.config.get("wgUserLanguage"); // Mobile detection: MobileFrontend sets wgMFMode, or fall back to touch check. var isMobile = !!mw.config.get("wgMFMode") || window.matchMedia("(pointer: coarse)").matches; var chosenOptions = { width: "20em", disable_search_threshold: 0, placeholder_text_single: "Yekî hilbijêre", placeholder_text_multiple: "Hilbijêre", no_results_text: "Nehat dîtin", enable_split_word_search: true, search_contains: true }; /** * On mobile, replaces chosen with a single-box autocomplete widget. * The user sees one <input>; typing filters a results list below it. * Selecting a result sets the hidden <select> value and fires "change" * so the rest of the form reacts normally. * * The original <select> is kept hidden so all existing .val() / change * bindings continue to work unchanged. */ function wrapNativeSelect(select) { var placeholder = select.attr("data-placeholder") || "Lê bigere…"; // Hide the native select — we drive it programmatically. select.hide(); var wrapper = $("<span class='wiktku-native-select-wrap'></span>"); var textInput = $("<input type='search' autocomplete='off'>") .attr("placeholder", placeholder) .addClass("wiktku-start-narrow wiktku-ac-input"); var resultsList = $("<ul class='wiktku-ac-results'></ul>").hide(); // Full option cache — rebuilt when chosen:updated fires. var allOptions = []; function cacheOptions() { allOptions = []; select.find("option").each(function () { var v = $(this).val(); if (!v) return; // skip the empty placeholder option allOptions.push({ value: v, text: $(this).text(), disabled: $(this).prop("disabled") }); }); } cacheOptions(); function showResults(query) { var q = query.trim().toLowerCase(); resultsList.empty(); var matched = q ? $.grep(allOptions, function (o) { return !o.disabled && o.text.toLowerCase().indexOf(q) !== -1; }) : allOptions.filter(function (o) { return !o.disabled; }); if (!matched.length) { resultsList.hide(); return; } $.each(matched.slice(0, 50), function (_, opt) { var li = $("<li></li>").text(opt.text).attr("data-value", opt.value); // Use touchend instead of touchstart so that a scroll gesture does // not accidentally select an item. We track whether the finger moved // between touchstart and touchend — if it did, it was a scroll. var touchMoved = false; li.on("touchstart", function () { touchMoved = false; }); li.on("touchmove", function () { touchMoved = true; }); li.on("touchend", function (e) { if (touchMoved) return; // was a scroll, not a tap e.preventDefault(); selectOption(opt.value, opt.text); }); // Keep mousedown for desktop fallback. li.on("mousedown", function (e) { e.preventDefault(); selectOption(opt.value, opt.text); }); resultsList.append(li); }); // Position the list above or below depending on available viewport space. var inputRect = textInput[0].getBoundingClientRect(); var viewportH = window.innerHeight; var spaceBelow = viewportH - inputRect.bottom - 8; var spaceAbove = inputRect.top - 8; var maxH = Math.min(224, Math.max(spaceBelow, spaceAbove)); // 224px ≈ 14em resultsList.css({ "max-height": maxH + "px", "top": spaceBelow >= spaceAbove ? "100%" : "auto", "bottom": spaceBelow >= spaceAbove ? "auto" : "100%" }); resultsList.show(); } function selectOption(value, text) { textInput.val(text); select.val(value); resultsList.hide(); select.trigger("change"); } textInput.on("input focus", function () { showResults($(this).val()); }); textInput.on("blur", function () { // Short delay so a touchstart on a result item fires first. setTimeout(function () { resultsList.hide(); }, 200); }); // chosen:updated → re-cache (called after ziman.json loads). select.on("chosen:updated", function () { cacheOptions(); // If a value is already selected, keep the display text in sync. var cur = select.val(); if (cur) { var match = $.grep(allOptions, function (o) { return o.value === cur; })[0]; if (match) textInput.val(match.text); } }); // No-op .chosen() so desktop call-sites don't need guarding. select.chosen = function () { return select; }; wrapper.append(textInput).append(resultsList).append(select); return wrapper; } var langsByCode = {}; // Populated from MediaWiki:Gadget-start.js/data.json at runtime. var metadata = {}; function needsTransliteration(langCode) { var meta = metadata[langCode]; if (!meta || !meta.sc) return false; var scripts = Array.isArray(meta.sc) ? meta.sc : [meta.sc]; return scripts.length > 0 && scripts[0] !== "Latn"; } // Kodên cinsiyetê yên di metadata.g de (li gorî peymana vê skrîptê: // m = mê, n = nêr, nt = nêtar, mn/c = mê û nêr, y = yekjimar, p = pirjimar) bo etîketên kurmancî. var GENDER_BASE_LABELS = { m: "mê", n: "nêr", nt: "nêtar", mn: "mê û nêr", g: "giştî", y: "yekjimar", p: "pirjimar" }; /** * Kodeke cinsiyetê (wek "m", "n-p", "p") vediguherîne etîketeke * kurmancî ya xwendinbar. Kodên "-p" forma pirjimar a wê cinsiyetê * nîşan didin. Kodên nenas (wek yên taybet ên hin zimanan) bi kodê * xwe re têne nîşandan, ne bi texmînek çewt. */ function genderLabel(code) { if (code === "p") return "Pirjimar"; var pluralMatch = code.match(/^(.+)-p$/); if (pluralMatch && GENDER_BASE_LABELS[pluralMatch[1]]) { return GENDER_BASE_LABELS[pluralMatch[1]] + " (pirjimar)"; } return GENDER_BASE_LABELS[code] || code; } /** * Rêzeke nimûneyan vediguherîne beşa wikînivîsê ya di bin tarîfekê de. * Her nimûne dikare xwedan { text, tr, t } be: * text — metnê nimûneyê * tr — transkrîpsiyon (tenê ger ziman hewceyî transliterasyonê be) * t — tercime bo kurmancî (parametreya sêyem a şablonê, bê nav) * Ger nimûne ji 200 tîpan kêmtir be |rêz=1 tê zêdekirin (ne ji bo ku). * Ger ti nimûne tinebe {{bênimûne|lang}} tê nivîsandin. */ function formatNimune(nimunes, lang) { var hasNimune = nimunes && $.grep(nimunes, function (n) { return (typeof n === "object" ? n.text : n) !== ""; }).length > 0; if (!hasNimune) { return "\n#* {{bênimûne|" + lang + "}}"; } return $.map(nimunes, function (n) { var text = typeof n === "object" ? n.text : n; if (!text) return undefined; var bolded = text.replace( new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"), "'''$1'''"); var tpl = "\n#: {{nm|" + lang + "|" + bolded; if (typeof n === "object") { if (n.tr) tpl += "|tr=" + n.tr; // Translation as third positional param (no key needed). if (n.t) tpl += "|" + n.t; } // Short examples fit on one line together with their translation. // rêz=1 is not used for ku — definitions are shown on separate lines there. if (text.length < 200 && lang !== "ku") tpl += "|rêz=1"; tpl += "}}"; return tpl; }).join(""); } /** * Formats a jêder (quote/citation) object into wikitext lines. * Returns empty string when no quote is present. * Output: * #* <quote> * #*: '''<quoteTr>''' (if transliteration present) * #*: <quoteT> (if translation present) * #** {{jêder-…|lang|jêgirtin=…|…fields…}} */ function formatJeder(jeder, lang) { if (!jeder || !jeder.quote) return ""; var out = "\n#* " + jeder.quote; if (jeder.quoteTr) out += "\n#*: '''" + jeder.quoteTr + "'''"; if (jeder.quoteT) out += "\n#*: " + jeder.quoteT; if (jeder.jêderTpl) { var cite = "\n#** {{" + jeder.jêderTpl + "|" + lang; cite += "|jêgirtin=" + jeder.quote; if (jeder.quoteTr) cite += "|tr=" + jeder.quoteTr; if (jeder.quoteT) cite += "|tercime=" + jeder.quoteT; $.each(jeder.jêderFields || {}, function (key, val) { if (val) cite += "|" + key + "=" + val; }); cite += "}}"; out += cite; } return out; } /** * Fabrîkeyek bo gavên "lîsteya kelîmeyan" ên hevşibin: jê, têkildar, binêre herwiha. Berê pênc caran bi hemû wek hev dihatin * nivîsandin; niha cudahiya wan tenê nav, pirs û sernivîsa wan e. */ function makeWordListStep(id, name, question_fmt, header, templateName) { return { id: id, name: name, question_fmt: question_fmt, multiple: true, narrow: true, visible: function (values) { return values.lang && values.pos; }, output: function (values) { var words = $.grep(values[id] || [], function (w) { return !!w; }); if (!words.length) return ""; var lang = values.lang; var section = "==== " + header + " ====\n"; if (words.length === 1) { // Single word — keep the simple inline template. return section + "* {{" + templateName + "|" + lang + "|" + words[0] + "}}\n\n"; } // Multiple words — use {{kol3}} with one positional param per word. var params = "|sernav=" + header + "\n" + $.map(words, function (w) { return "|" + w; }).join("\n"); return section + "{{kol3|" + lang + "\n" + params + "\n}}\n\n"; } }; } var steps = { lang: { id: "lang", required: true, name: "ziman", question_fmt: "“{{PAGENAME}}” bi çi zimanî ye?", question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (langChoices). choices: [], output: function (values) { return "== {{ziman|" + values.lang + "}} ==\n\n"; } }, pron: { id: "pron", name: "bilêvkirin", question_fmt: "“{{PAGENAME}}” çawa tê telafûzkirin?", // pronTpls populated from data.json pronTpls: [], visible: function (values) { return !!values.lang; }, /** Fills (or refills) the insert-dropdown from the current pronTpls array, filtering by language. */ refreshTplSelect: function () { var sel = $("#wiktku-start-pron .wiktku-tpl-insert-select"); if (!sel.length) return; var lang = getValues().lang || ""; sel.find("option[value!='']").remove(); $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-pron-wrap").length) return null; var wrap = $("<div class='wiktku-pron-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-pron-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-pron-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{IPA|ku|/pɛɪ̯n/}} yan {{kîte|ku|peyn}}"); // Template insert dropdown — filtered by language. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); var lang = getValues().lang || ""; $.each(steps.pron.pronTpls, function (_, tpl) { // Filter: if tpl.langs exists, only show if lang is in that list; otherwise show always var allowed = !tpl.langs || tpl.langs.indexOf(lang) !== -1; if (allowed) { sel.append($("<option></option>") .val(tpl.snippet) .text(tpl.name + " — " + tpl.desc) .attr("data-nolang", tpl.noLang ? "1" : "")); } }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; // Check if the selected option has noLang flag var selectedOption = sel.find("option:selected"); var hasNoLang = selectedOption.attr("data-nolang") === "1"; if (!hasNoLang) { snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); } insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-pron .wiktku-pron-text").val()); if (!text) return ""; var lines = text.split("\n"); var out = $.map(lines, function (line) { line = $.trim(line); if (!line) return undefined; return line.charAt(0) === "*" ? line : "* " + line; }).join("\n"); return "=== Bilêvkirin ===\n" + out + "\n\n"; } }, pos: { id: "pos", required: true, name: "Cureyê rêzimanî", question_fmt: "Cureyê rêzimanî yê “{{PAGENAME}}” çi ye?", visible: function (values) { return values.lang; }, question_br: true, // Populated from MediaWiki:Gadget-start.js/data.json (posChoices). choices: [], output: function (values) { var pos = values.pos || ""; var cinsiyet = values.cinsiyet || ""; // from the cinsiyet step var lekTur = values.lektur || ""; // from the lêker transitivity step var capitalizedPos = capitalize(pos); var outputString = "=== " + capitalizedPos + " ===\n"; // Gender-to-Kurmancî name map (used by ku-tewîn-nav). // "nt" tê de nîne bi qesd — ne bi "mn" tê wekhevkirin (li gorî // biryara berê), loma ji bo "nt" şablona ku-tewîn-nav nayê zêdekirin. var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" }; // Add ku-tewîn-nav for single-word navdêr/serenav with known gender. if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] && (pos === "navdêr" || pos === "serenav") && values.lang === "ku") { outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n"; } outputString += "{{" + pos + "|" + values.lang; if (pos === "navdêr" || pos === "serenav") { if (cinsiyet) { outputString += "|c=" + cinsiyet; } else if (values.lang === "ku") { // Unknown gender — prompt editor to fill it in. outputString += "|c=?"; } } else if (/^lêker/.test(pos) && lekTur) { outputString += "|c=" + lekTur; } if (values.tr) { outputString += "|tr=" + values.tr; } outputString += "}}\n"; return outputString; } }, /** * cinsiyet (grammatical gender) — only shown for navdêr/serenav, û * tenê ger metadata ji bo zimanê hilbijartî lîsteyeke "g" (cinsiyet) * were dayîn. Bijardeyên vê gavê ne sabît in — ji metadata[values.lang].g * têne çêkirin, ji ber ku ne hemû ziman heman cinsiyetan hene (an qet * cinsiyet nînin). */ cinsiyet: { id: "cinsiyet", name: "cinsiyet", question_fmt: "Cinsiyeta kelîmeyê çi ye?", question_br: true, visible: function (values) { var meta = metadata[values.lang]; return !!(values.lang && (values.pos === "navdêr" || values.pos === "serenav") && meta && meta.g && meta.g.length); }, build: function (stepDiv, values) { var select = stepDiv.find("select.wiktku-start-step-field"); if (!select.length) { select = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-cinsiyet-field" })); stepDiv.append(select); } // Gava yekem (ji build()-a giştî) values nayê şandin — hîna // ziman nehatiye hilbijartin, ji ber vê tenê select-a vala // vegerîne, dê bi refresh() were dagirtin. if (!values) return select; var meta = metadata[values.lang]; var codes = (meta && meta.g) || []; var prevVal = select.val(); var choices = $.map(codes, function (code) { return [[code, genderLabel(code)]]; }); populateMenus(select, choices); if ($.grep(choices, function (c) { return c[0] === prevVal; }).length) { select.val(prevVal); } if (!isMobile) select.trigger("chosen:updated"); return select; }, output: function () { return ""; } // consumed by pos.output }, /** * Lêker transitivity — only shown for any lêker variant. * Add new transitivity values to the choices dict here. */ lektur: { id: "lektur", name: "Cureyê lêkerê", question_fmt: "Cureyê lêkerê çi ye?", question_br: true, visible: function (values) { return values.lang && values.pos && /^lêker/.test(values.pos); }, // Dictionary: value → display label. Add new types here. choices: [ ["gh", "Gerguhêz"], ['x-gh', 'Xwerû-gerguhêz'], ['p-gh', 'pêkhatî-gerguhêz'], ['h-gh', 'hevedudanî-gerguhêz'], ['b-gh', 'biwêjî-gerguhêz'], ["ngh", "Negerguhêz"], ['x-ngh', 'xwerû-negerguhêz'], ['p-ngh', 'pêkhatî-negerguhêz'], ['h-ngh', 'hevedudanî-negerguhêz'], ['b-ngh', 'biwêjî-negerguhêz'] ], output: function () { return ""; } // consumed by pos.output }, tr: { id: "tr", name: "transkrîpsiyon", question_fmt: "Transkrîpsiyona kelîmeyê", multiple: false, narrow: true, visible: function (values) { return values.lang && values.pos && needsTransliteration(values.lang); } }, dfn: { id: "dfn", // required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne name: "Mane", question_fmt: "Mane û nimûneyên kelîmeyê binivîse. Ji bo tercimeyan beşa 'Werger' bi kar bîne!", multiple: true, ordered: true, rows: 3, visible: function (values) { return values.lang && values.pos; }, example: function (values) { // posExamples loaded from MediaWiki:Gadget-start.js/data.json. // Keys may be the exact chosen pos value (e.g. "lêker/gh"), or // just its base form before the "/" (e.g. "lêker") for pos // values shared across variants — try the exact value first, // then fall back to the base form. var examples = steps.dfn.posExamples || {}; var full = values.pos || ""; var base = full.split("/")[0]; return examples[full] || examples[base] || ""; }, /** * Builds one sense block (<li>) inside the ordered list. * Each block contains: * - a textarea for the definition * - an expandable nimûne list * - single-row sub-lists for herwiha, hevmane, dijmane */ buildSenseBlock: function (stepDiv) { var block = $("<li class='wiktku-dfn-sense'></li>"); // — Mane textarea (declared first so the template handler can reference it) — var dfnArea = $("<textarea></textarea>") .attr("name", "wiktku-dfn-mane-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", "wiktku-start-step-field wiktku-dfn-mane") .attr("rows", 6) .attr("placeholder", "Mane…"); dfnArea.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); // — Template selector (optional — replaces mane when chosen) — // Template definitions loaded from MediaWiki:Gadget-start.js/data.json. var tplDefs = steps.dfn.tplDefs || []; // Cache of all non-placeholder option elements — used by updateTplOptions // to remove/re-add options (the only approach compatible with Chosen.js). var _allTplOptions = []; var tplSelect = $(mw.html.element("select", { "class": "wiktku-dfn-tpl-select" })); tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>")); $.each(tplDefs, function (_, tpl) { var opt = $("<option></option>") .val(tpl.name) .text(tpl.name) .attr("data-langs", tpl.langs ? tpl.langs.join(",") : "") .attr("data-nolang", tpl.noLang ? "1" : ""); tplSelect.append(opt); _allTplOptions.push(opt[0]); }); function updateTplOptions() { var lang = getValues().lang || ""; var currentVal = tplSelect.val(); var currentStillValid = false; // Detach all non-placeholder options, then re-attach only the visible ones. // This is the only approach that works correctly with both native <select> // and Chosen.js on desktop. tplSelect.find("option[value!='']").detach(); $.each(_allTplOptions, function (_, opt) { var allowed = $(opt).attr("data-langs"); var visible = !allowed || allowed.split(",").indexOf(lang) !== -1; if (visible) { tplSelect.append(opt); if ($(opt).val() === currentVal) currentStillValid = true; } }); if (!isMobile) tplSelect.trigger("chosen:updated"); if (currentVal && !currentStillValid) { tplSelect.val(""); dfnArea.show(); tplTitleInput.hide().val(""); } } // Store updater on the element so refresh() can call it for all blocks. tplSelect.data("updateOptions", updateTplOptions); var tplTitleInput = $("<input type='text'>") .addClass("wiktku-dfn-tpl-title wiktku-start-narrow") .attr("placeholder", "Navê rûpelê…") .hide(); // Grow the sense list when the title field of the last block gets content, // mirroring what onDfnInput does for the plain mane textarea. tplTitleInput.on("input", function () { steps.dfn.onDfnInput(stepDiv, block, this); }); tplSelect.on("change", function () { var chosen = $(this).val(); if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); } else { dfnArea.show(); tplTitleInput.hide().val(""); } // Re-run refresh so the Werger step visibility updates. refresh(); }); var tplRow = $("<div></div>").addClass("wiktku-dfn-tpl-row") .append(tplSelect).append(" ").append(tplTitleInput); block.append(tplRow); block.append(dfnArea); // Apply lang filter on initial build. updateTplOptions(); // — Inline links row: (+ Etîket) + all lazy sub-group triggers — // Sits right before the Nimûne textarea; all lazy fields are revealed by clicking their link. var lazyLinksDiv = null; // no longer used — all groups are always visible // — Sub-field groups — // All groups are always visible with a placeholder textarea. // Nimûne is last in the DOM and last in the output. var allGroups = [ { cls: "wiktku-dfn-etiket", label: "Etîket", rows: 1, narrow: true }, { cls: "wiktku-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true }, { cls: "wiktku-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }, { cls: "wiktku-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true }, { cls: "wiktku-dfn-jornav", label: "Jornav", rows: 1, narrow: true }, { cls: "wiktku-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }, { cls: "wiktku-dfn-nimune", label: "Nimûne", rows: 2, narrow: false } ]; $.each(allGroups, function (_, g) { var groupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup " + g.cls + "-group"); if (g.cls === "wiktku-dfn-nimune") { // Nimûne — compound widget with tr/t sub-fields. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); function buildNimuneLi() { var lang = getValues().lang || ""; var li = $("<li></li>").addClass("wiktku-dfn-nimune-li"); var mainTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-text-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-text") .attr("placeholder", "Nimûne…"); mainTa.on("input", function () { var val = $.trim($(this).val()); var isLast = li.is(list.children("li:last-child")); if (val && isLast) { list.append(buildNimuneLi()); } }); li.append(mainTa); var subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); if (needsTransliteration(lang)) { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…") ); } if (lang && lang !== "ku") { subWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…") ); } if (subWrap.children().length) li.append(subWrap); return li; } groupDiv.data("buildNimuneLi", buildNimuneLi); list.append(buildNimuneLi()); groupDiv.append(lbl).append(list); block.append(groupDiv); } else { // Regular always-visible group — label + growing textarea list. var lbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text(g.label + ": "); var list = $("<ol></ol>").addClass("wiktku-dfn-sublist " + g.cls + "-list"); var firstInput = $("<textarea></textarea>") .attr("name", g.cls + "-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", g.rows) .attr("class", "wiktku-dfn-subfield" + (g.narrow ? " wiktku-start-narrow" : "")) .attr("placeholder", g.label + "…"); firstInput.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); }); list.append($("<li></li>").append(firstInput)); groupDiv.append(lbl).append(list); block.append(groupDiv); } }); // — Jêder (quote / citation) group — always visible, sibling to Nimûne — (function () { var lang = getValues().lang || ""; var jederGroupDiv = $("<div></div>").addClass("wiktku-dfn-subgroup wiktku-dfn-jeder-group"); var jederLbl = $("<span></span>").addClass("wiktku-dfn-sublabel").text("Jêder: "); // Quote text textarea var quoteTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote") .attr("placeholder", "Jêgirtin…"); // tr/t sub-fields for the quote var quoteSubWrap = $("<div></div>").addClass("wiktku-dfn-quote-sub"); if (needsTransliteration(lang)) { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-tr") .attr("placeholder", "Transkrîpsiyona jêgirtinê…") ); } if (lang && lang !== "ku") { quoteSubWrap.append( $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-quote-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 2) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-quote-t") .attr("placeholder", "Tercimeya jêgirtinê (kurmancî)…") ); } // Source template selector var srcSel = $("<select></select>").addClass("wiktku-dfn-quote-src-sel"); srcSel.append($("<option value=''>— Çavkaniyê hilbijêre —</option>")); var jederDefs = steps.dfn.jederDefs || {}; $.each(jederDefs, function (tplName, def) { srcSel.append($("<option></option>").val(tplName).text(def.label)); }); // Dynamic source fields container var srcFields = $("<div></div>").addClass("wiktku-dfn-quote-src-fields"); srcSel.on("change", function () { srcFields.empty(); var chosen = $(this).val(); if (!chosen) return; var def = (steps.dfn.jederDefs || {})[chosen]; if (!def) return; $.each(def.fields, function (_, f) { var row = $("<div></div>").addClass("wiktku-dfn-quote-src-row"); var fieldLbl = $("<label></label>").text(f.label + ": "); var inp = $("<input type='text'>") .addClass("wiktku-dfn-quote-src-input wiktku-start-narrow") .attr("data-field-key", f.key) .attr("placeholder", f.label + "…"); row.append(fieldLbl).append(inp); srcFields.append(row); }); }); jederGroupDiv.append(jederLbl).append(quoteTa); if (quoteSubWrap.children().length) jederGroupDiv.append(quoteSubWrap); jederGroupDiv.append(srcSel).append(srcFields); block.append(jederGroupDiv); }()); return block; }, /** Grows the sense list when the last mane textarea gets content. */ onDfnInput: function (stepDiv, block, textarea) { var val = $.trim($(textarea).val()); var list = stepDiv.find("ol.wiktku-dfn-list"); var isLast = block.is(list.children("li:last-child")); if (val && isLast) { var newBlock = steps.dfn.buildSenseBlock(stepDiv); list.append(newBlock); // Apply Chosen to the new block's template selector on desktop. if (!isMobile) newBlock.find("select.wiktku-dfn-tpl-select").chosen(chosenOptions); } refresh(); }, /** Grows a sub-list (nimûne/herwiha/hevmane/dijmane/termên koordîne) on input. */ onSubInput: function (list, input, rows, narrow) { var val = $.trim($(input).val()); var item = $(input).parent(); var isLast = item.is(list.children("li:last-child")); if (val && isLast) { var next = $("<textarea></textarea>") .attr("name", "wiktku-dfn-sub-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", rows) .attr("class", "wiktku-dfn-subfield" + (narrow ? " wiktku-start-narrow" : "")); next.on("input", function () { steps.dfn.onSubInput(list, this, rows, narrow); }); list.append($("<li></li>").append(next)); } }, // Populated from MediaWiki:Gadget-start.js/data.json (tplDefs). tplDefs: [], // Populated from MediaWiki:Gadget-start.js/data.json (posExamples). posExamples: {}, // Populated from MediaWiki:Gadget-start.js/data.json (jederDefs). jederDefs: {}, build: function (stepDiv) { // Guard: only build once — refresh() calls build() on every // unrelated change, so skip if the list is already present. if (stepDiv.find("ol.wiktku-dfn-list").length) return null; var list = $("<ol class='wiktku-dfn-list'></ol>"); list.append(steps.dfn.buildSenseBlock(stepDiv)); stepDiv.append(list); return null; }, /** Reads all sense blocks from the DOM and returns an array of sense objects. */ getSenses: function (stepDiv) { var senses = []; stepDiv.find("li.wiktku-dfn-sense").each(function () { var block = $(this); var tplSel = block.find("select.wiktku-dfn-tpl-select"); var tpl = tplSel.val() || ""; // noLang: template already encodes the language — don't add |lang| param. var tplNoLang = tpl ? tplSel.find("option[value='" + tpl + "']").attr("data-nolang") === "1" : false; var tplTitle = $.trim(block.find("input.wiktku-dfn-tpl-title").val()); var mane = $.trim(block.find("textarea.wiktku-dfn-mane").val()); var etiket = (function () { var vals = []; block.find(".wiktku-dfn-etiket-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; }()); function readList(cls) { var vals = []; block.find("." + cls + "-list textarea").each(function () { var v = $.trim($(this).val()); if (v) vals.push(v); }); return vals; } // Nimûne items are compound: { text, tr?, t? } function readNimuneList() { var items = []; block.find(".wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var text = $.trim($(this).find(".wiktku-dfn-nimune-text").val()); if (!text) return; var obj = { text: text }; var tr = $.trim($(this).find(".wiktku-dfn-nimune-tr").val()); var t = $.trim($(this).find(".wiktku-dfn-nimune-t").val()); if (tr) obj.tr = tr; if (t) obj.t = t; items.push(obj); }); return items; } // Quote / citation data lives at the sense-block level (not per nimune item). function readJeder() { var jederGroup = block.find(".wiktku-dfn-jeder-group"); var quote = $.trim(jederGroup.find(".wiktku-dfn-nimune-quote").val()); if (!quote) return null; var obj = { quote: quote }; var qtr = $.trim(jederGroup.find(".wiktku-dfn-nimune-quote-tr").val()); var qt = $.trim(jederGroup.find(".wiktku-dfn-nimune-quote-t").val()); if (qtr) obj.quoteTr = qtr; if (qt) obj.quoteT = qt; var tplName = jederGroup.find(".wiktku-dfn-quote-src-sel").val(); if (tplName) { obj.jêderTpl = tplName; var fields = {}; jederGroup.find(".wiktku-dfn-quote-src-input").each(function () { var k = $(this).attr("data-field-key"); var v = $.trim($(this).val()); if (k && v) fields[k] = v; }); obj.jêderFields = fields; } return obj; } senses.push({ tpl: tpl, tplNoLang: tplNoLang, tplTitle: tplTitle, mane: mane, etiket: etiket, nimune: readNimuneList(), jeder: readJeder(), herwiha: readList("wiktku-dfn-herwiha"), hevmane: readList("wiktku-dfn-hevmane"), dijmane: readList("wiktku-dfn-dijmane"), koordine: readList("wiktku-dfn-koordine"), jornav: readList("wiktku-dfn-jornav"), jernav: readList("wiktku-dfn-jernav") }); }); return senses; }, getOutput: function (values, callback) { var stepDiv = $("#wiktku-start-dfn"); var senses = steps.dfn.getSenses(stepDiv); var lang = values.lang; // A sense counts as "filled" if it has either a mane or a chosen template + title. var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); }); // True only when at least one sense has a regular mane (needs linkify). var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; }); var text = $.map(senses, function (sense) { // — Template sense (e.g. {{Guharto|ku|somepage}} or {{ku-Latn|somepage}}) — if (sense.tpl) { if (!sense.tplTitle) return undefined; // noLang templates encode the language in their name — omit the |lang| param. if (sense.tplNoLang) { return "# {{" + sense.tpl + "|" + sense.tplTitle + "}}"; } return "# {{" + sense.tpl + "|" + lang + "|" + sense.tplTitle + "}}"; } // — Normal mane sense — var dfn = sense.mane; if (!dfn) return undefined; // Capitalize and punctuate. if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn); if (!dfn.match(/[.…?!)\]]$/)) dfn += "."; // {{e|lang|label1|label2}} var labelTpl = ""; if (sense.etiket && sense.etiket.length) { var labelParts = sense.etiket.map(function (part) { return $.trim(part); }).filter(function (part) { return part !== ""; }); if (labelParts.length) { labelTpl = " {{e|" + lang + "|" + labelParts.join("|") + "}} "; } } var out = "#" + (labelTpl ? labelTpl : " ") + dfn; // Per-sense word lists as #: template lines. function wordLine(tpl, words) { if (!words.length) return ""; return "\n#: {{" + tpl + "|" + lang + "|" + words.join("|") + "}}"; } out += wordLine("herwiha-rêz", sense.herwiha); out += wordLine("hevmane", sense.hevmane); out += wordLine("dijmane", sense.dijmane); out += wordLine("termên koordîne", sense.koordine); out += wordLine("jornav", sense.jornav); out += wordLine("jêrnav", sense.jernav); // Nimûne lines — always last. out += formatNimune(sense.nimune, lang); // Jêder (quote/citation) — after nimune. out += formatJeder(sense.jeder, lang); return out; }).join("\n") + "\n\n"; if (!hasMane) { // No definitions entered — emit {{mane?}} with bênimûne. text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n"; callback(text); return; } if (!hasRegularMane) { // All filled senses are template senses — no linkify needed. callback(text); return; } var didTryToLoad = function () { // If the module failed to load, $.wiktviLinkify won't exist — // fall back to the unlinkified text instead of throwing. if (typeof $.wiktviLinkify === "function") { $.wiktviLinkify(text, callback); } else { callback(text); } }; mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad); } }, je: makeWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"), tekildar: makeWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"), binereherwiha: makeWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"), etym: { id: "etym", name: "etîmolojî", question_fmt: "Etîmolojiya kelîmeyê binivîse", // etymTpls populated from data.json etymTpls: [], visible: function (values) { return values.lang && values.pos; }, /** Fills (or refills) the insert-dropdown from the current etymTpls array. */ refreshTplSelect: function () { var sel = $("#wiktku-start-etym .wiktku-tpl-insert-select"); if (!sel.length) return; sel.find("option[value!='']").remove(); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); // Notify Chosen that the option list has changed (no-op on mobile). if (!isMobile) sel.trigger("chosen:updated"); }, build: function (stepDiv) { if (stepDiv.find(".wiktku-etym-wrap").length) return null; var wrap = $("<div class='wiktku-etym-wrap'></div>"); var ta = $("<textarea></textarea>") .attr("name", "wiktku-etym-" + $.now()) .attr("class", "wiktku-start-step-field wiktku-etym-text") .attr("rows", 4) .attr("placeholder", "Mînak: {{ji|en|ku|apple}} yan rasterast binivîse…"); // Template insert dropdown — options also refreshed after data.json loads. var sel = $("<select class='wiktku-tpl-insert-select'></select>"); sel.append($("<option value=''>— şablonek lê zêde bike —</option>")); $.each(steps.etym.etymTpls, function (_, tpl) { sel.append($("<option></option>").val(tpl.snippet).text(tpl.name + " — " + tpl.desc)); }); sel.on("change", function () { var snippet = $(this).val(); if (!snippet) return; var lang = getValues().lang || ""; snippet = snippet.replace(/LANG/g, lang).replace(/SOURCELANG/g, "?"); insertAtCursor(ta[0], snippet); $(this).val(""); ta.focus(); }); wrap.append(sel).append($("<br>")).append(ta); stepDiv.append(wrap); return ta; }, output: function (values) { var text = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); if (text) { return "==== Etîmolojî ====\n" + text + "\n\n"; } // No etymology entered — emit {{ji?|lang}} as a placeholder, // but only when the entry has at least one regular mane sense // (not a template sense like {{guharto|…}}). var hasRegularMane = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { var tpl = $(this).find("select.wiktku-dfn-tpl-select").val(); var mane = $.trim($(this).find("textarea.wiktku-dfn-mane").val()); if (!tpl && mane) { hasRegularMane = true; return false; // break } }); if (!hasRegularMane) return ""; return "==== Etîmolojî ====\n{{ji?|" + values.lang + "}}\n\n"; } }, trans: { id: "trans", name: "werger", visible: function (values) { if (!(values.lang === "ku" && values.pos)) return false; // Hide Werger when at least one sense uses a template instead of a mane. var hasTemplateSense = false; $("#wiktku-start-dfn li.wiktku-dfn-sense").each(function () { if ($(this).find("select.wiktku-dfn-tpl-select").val()) { hasTemplateSense = true; return false; // break } }); return !hasTemplateSense; }, disabledKeys: { "navz": true, "ku": true }, /** * Builds one translation row: a language dropdown + a growing list * of word inputs. When the dropdown gets a value the next empty row * is appended automatically. */ buildRow: function (stepDiv) { var row = $("<li class='wiktku-trans-row'></li>"); // Language selector — chosen is applied after insertion into DOM. var langSel = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); langSel.attr("data-placeholder", "Zimanekî hilbijêre"); populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys); // When a language is chosen, ensure a next empty row exists. langSel.on("change", function () { steps.trans.onLangChange(stepDiv, row); }); // Word list for this language. var wordList = $("<ul class='wiktku-trans-words'></ul>"); var firstWord = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(firstWord)); if (isMobile) { row.append(wrapNativeSelect(langSel)).append(wordList); } else { row.append(langSel).append(wordList); } return row; }, makeWordInput: function () { var input = $("<textarea></textarea>") .attr("name", "wiktku-trans-word-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .attr("placeholder", "Tercime…"); input.on("input", function () { var list = $(this).closest("ul.wiktku-trans-words"); var item = $(this).parent(); var val = $.trim($(this).val()); if (val && item.is(list.children("li:last-child"))) { var next = steps.trans.makeWordInput(); list.append($("<li></li>").append(next)); } }); return input; }, onLangChange: function (stepDiv, row) { var list = stepDiv.find("ul.wiktku-trans-list"); var isLast = row.is(list.children("li.wiktku-trans-row:last-child")); if (isLast) { var newRow = steps.trans.buildRow(stepDiv); list.append(newRow); // Init chosen after the new row is in the DOM (desktop only). if (!isMobile) newRow.find("select").chosen(chosenOptions); } // Keep disabled keys in sync across all lang selectors. steps.trans.syncDisabledKeys(stepDiv); }, /** Disables already-selected languages in all other dropdowns. */ syncDisabledKeys: function (stepDiv) { var taken = $.extend({}, steps.trans.disabledKeys); stepDiv.find("li.wiktku-trans-row select").each(function () { var v = $(this).val(); if (v) taken[v] = true; }); stepDiv.find("li.wiktku-trans-row select").each(function () { var self = $(this); var own = self.val(); self.find("option").each(function () { var code = $(this).val(); if (!code) return; $(this).prop("disabled", taken[code] && code !== own); }); self.trigger("chosen:updated"); }); }, build: function (stepDiv) { if (stepDiv.find("ul.wiktku-trans-list").length) return null; var list = $("<ul class='wiktku-trans-list'></ul>"); list.append(steps.trans.buildRow(stepDiv)); stepDiv.append(list); // Init chosen after the select is in the DOM (desktop only). if (!isMobile) list.find("select").chosen(chosenOptions); return null; }, /** Reads all translation rows from the DOM. */ getTranslations: function (stepDiv) { var result = []; stepDiv.find("li.wiktku-trans-row").each(function () { var lang = $(this).find("select").val(); if (!lang) return; var words = []; $(this).find("ul.wiktku-trans-words textarea").each(function () { var v = $.trim($(this).val()); if (v) words.push(v); }); if (words.length) result.push([lang, words]); }); return result; }, output: function (values) { if (values.lang !== "ku") return ""; var stepDiv = $("#wiktku-start-trans"); var rows = steps.trans.getTranslations(stepDiv); var outputString = "\n\n==== Werger ====\n{{werger-ser}}"; if (rows.length) { // Sort by Kurdish sort key. rows.sort(function (a, b) { var aLang = langsByCode[a[0]] || []; var bLang = langsByCode[b[0]] || []; return (aLang[2] || "").localeCompare(bLang[2] || "", "ku"); }); outputString += "\n" + $.map(rows, function (row) { var lang = row[0]; var words = row[1]; var wikiWords = words.map(function (w) { return "{{W|" + lang + "|" + w + "}}"; }).join(", "); return "* {{Z|" + lang + "}}: " + wikiWords; }).join("\n"); } outputString += "\n{{werger-bin}}\n\n"; return outputString; } }, }; steps.trans.keys = steps.lang.choices; var ordered_steps = [ steps.lang, steps.pron, steps.pos, steps.cinsiyet, steps.lektur, steps.tr, steps.dfn, steps.je, steps.tekildar, steps.etym, steps.binereherwiha, steps.trans]; // Step ids that belong to each section (not shared across sections). var PER_SECTION_STEP_IDS = [ "pos", "cinsiyet", "lektur", "tr", "dfn", "je", "tekildar", "etym", "binereherwiha", "trans" ]; // ── Multi-section state ────────────────────────────────────────────────── // Each entry is a plain snapshot: { pos, cinsiyet, lektur, tr, dfn (senses[]), // je, tekildar, binereherwiha, trans (rows[]) }. var sections = [{}]; // section 0 starts empty (DOM is the truth) var activeSection = 0; /** * Read dfn senses from DOM into a serialisable array. * Extends getSenses() with the template fields. */ function snapshotDfn() { return steps.dfn.getSenses($("#wiktku-start-dfn")); } /** * Rebuild the dfn DOM from a previously snapshotted senses array. */ function restoreDfn(senses) { var stepDiv = $("#wiktku-start-dfn"); // Tear down the existing list so build() recreates it cleanly. stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); var list = stepDiv.find("ol.wiktku-dfn-list"); $.each(senses, function (i, sense) { // Ensure enough blocks exist (build() seeds one). var blocks = list.find("li.wiktku-dfn-sense"); var block = blocks.eq(i); if (!block.length) { var nb = steps.dfn.buildSenseBlock(stepDiv); list.append(nb); block = list.find("li.wiktku-dfn-sense").last(); } // Template selector. block.find("select.wiktku-dfn-tpl-select").val(sense.tpl || ""); if (sense.tpl) { block.find("textarea.wiktku-dfn-mane").hide(); block.find("input.wiktku-dfn-tpl-title").val(sense.tplTitle || "").show(); } else { block.find("textarea.wiktku-dfn-mane").val(sense.mane || "").show(); block.find("input.wiktku-dfn-tpl-title").hide().val(""); } // Restore a sub-list (etiket, herwiha, hevmane …) from a values array. function restoreSubList(cls, values) { if (!values || !values.length) return; var groupDiv = block.find("." + cls + "-group"); var subList = groupDiv.find("ol, ul").first(); if (!subList.length) return; // group not found // Fill existing items, append new ones as needed. $.each(values, function (j, val) { var items = subList.find("li"); if (j < items.length) { items.eq(j).find("textarea").val(val); } else { var ta = $("<textarea></textarea>") .attr("name", "wiktku-dfn-restore-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 1) .attr("class", "wiktku-dfn-subfield wiktku-start-narrow") .val(val); ta.on("input", function () { steps.dfn.onSubInput(subList, this, 1, true); }); subList.append($("<li></li>").append(ta)); } }); } // Reveal and populate lazy groups that have data. var lazyMap = { "wiktku-dfn-etiket": sense.etiket, "wiktku-dfn-herwiha": sense.herwiha, "wiktku-dfn-hevmane": sense.hevmane, "wiktku-dfn-dijmane": sense.dijmane, "wiktku-dfn-koordine": sense.koordine, "wiktku-dfn-jornav": sense.jornav, "wiktku-dfn-jernav": sense.jernav }; $.each(lazyMap, function (cls, vals) { if (vals && vals.length) restoreSubList(cls, vals); }); // Nimûne items are objects { text, tr?, t? } — restore using the builder. if (sense.nimune && sense.nimune.length) { var nimuneGroupDiv = block.find(".wiktku-dfn-nimune-group"); var nimuneList = nimuneGroupDiv.find("ol.wiktku-dfn-nimune-list"); var buildFn = nimuneGroupDiv.data("buildNimuneLi"); nimuneList.empty(); $.each(sense.nimune, function (_, n) { var text = typeof n === "object" ? (n.text || "") : n; if (!text) return; var li = buildFn ? buildFn() : $("<li class='wiktku-dfn-nimune-li'></li>"); li.find(".wiktku-dfn-nimune-text").val(text); if (n.tr) li.find(".wiktku-dfn-nimune-tr").val(n.tr); if (n.t) li.find(".wiktku-dfn-nimune-t").val(n.t); nimuneList.append(li); }); // Always leave a blank trailing item. if (buildFn) nimuneList.append(buildFn()); } // Restore jêder (quote/citation) data into the sense-block-level group. if (sense.jeder && sense.jeder.quote) { var jederGroup = block.find(".wiktku-dfn-jeder-group"); jederGroup.find(".wiktku-dfn-nimune-quote").val(sense.jeder.quote); if (sense.jeder.quoteTr) jederGroup.find(".wiktku-dfn-nimune-quote-tr").val(sense.jeder.quoteTr); if (sense.jeder.quoteT) jederGroup.find(".wiktku-dfn-nimune-quote-t").val(sense.jeder.quoteT); if (sense.jeder.jêderTpl) { var srcSel = jederGroup.find(".wiktku-dfn-quote-src-sel"); srcSel.val(sense.jeder.jêderTpl).trigger("change"); if (sense.jeder.jêderFields) { $.each(sense.jeder.jêderFields, function (key, val) { jederGroup.find(".wiktku-dfn-quote-src-input[data-field-key='" + key + "']").val(val); }); } } } }); } /** * Snapshot simple (non-dfn) per-section steps from current DOM into obj. */ function saveCurrentSection() { var snap = {}; $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { snap.dfn = snapshotDfn(); return; } if (id === "etym") { snap.etym = $.trim($("#wiktku-start-etym .wiktku-etym-text").val()); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); if (id === "trans") { snap.trans = steps.trans.getTranslations(stepDiv); return; } // Generic: read all step fields. var fields = stepDiv.find(".wiktku-start-step-field"); if (step.multiple) { snap[id] = fields.map(function () { return $(this).val(); }).get(); } else { snap[id] = fields.val(); } }); sections[activeSection] = snap; } /** * Restore a previously saved snapshot into the form DOM. */ function restoreSection(snap) { $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { restoreDfn(snap.dfn || []); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); $("#wiktku-start-etym .wiktku-etym-text").val(snap.etym || ""); return; } if (id === "trans") { // Rebuild trans rows. var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); steps.trans.build(transDiv); var rows = snap.trans || []; $.each(rows, function (i, row) { var lang = row[0], words = row[1]; var list = transDiv.find("ul.wiktku-trans-list"); var lastRow = list.find("li.wiktku-trans-row").last(); lastRow.find("select").val(lang).trigger("change"); var wordList = lastRow.find("ul.wiktku-trans-words"); $.each(words, function (j, word) { var wordItems = wordList.find("li"); if (j < wordItems.length) { wordItems.eq(j).find("textarea").val(word); } else { // .val() below doesn't fire "input", so the normal // auto-grow never runs — append a matching item // ourselves instead of silently dropping the word. var extraInput = steps.trans.makeWordInput(); wordList.append($("<li></li>").append(extraInput)); extraInput.val(word); } }); // Leave one trailing empty field so the row can still grow // when the user types, matching a freshly-built row. if ($.trim(wordList.children("li").last().find("textarea").val())) { wordList.append($("<li></li>").append(steps.trans.makeWordInput())); } }); return; } var step = steps[id]; if (!step) return; var stepDiv = $("#wiktku-start-" + id); var fields = stepDiv.find(".wiktku-start-step-field"); var val = snap[id]; if (val === undefined || val === null) return; if (step.multiple) { var arr = val; fields.each(function (i) { if (i < arr.length) $(this).val(arr[i]); }); } else { fields.val(val); } // Notify chosen widgets of the programmatic value change. if (!isMobile) fields.filter("select").trigger("chosen:updated"); }); } /** * Produce wikitext for the currently-visible form state. * This is identical to the old getWikitext but returns via callback. */ function getWikitextForCurrentSection(callback) { var values = getValues(); var entry = steps.pos.output(values); steps.dfn.getOutput(values, function (output) { entry += output; entry += steps.je.output(values); entry += steps.tekildar.output(values); entry += steps.etym.output(values); entry += steps.binereherwiha.output(values); entry += steps.trans.output(values); callback(entry, values); }); } /** * Collect wikitext from ALL sections by save→restore→generate cycling, * then restore the originally active section. */ function getWikitextAllSections(callback) { saveCurrentSection(); var results = new Array(sections.length); var sharedValues = getValues(); // lang/pron are shared function processSection(i) { if (i >= sections.length) { // All done — restore original active section. restoreSection(sections[activeSection]); refresh(); callback(results, sharedValues); return; } restoreSection(sections[i]); refresh(); getWikitextForCurrentSection(function (sectionText) { results[i] = sectionText; processSection(i + 1); }); } processSection(0); } /** * The original getWikitext — now assembles all sections plus lang header. */ function getWikitext(callback) { getWikitextAllSections(function (sectionTexts, sharedValues) { var entry = steps.lang.output(sharedValues); entry += steps.pron.output(sharedValues); entry += sectionTexts.join("\n"); // Edit summary uses section 0's values. Read from the saved snapshot // (not the live DOM) so it doesn't mix section 0's pos with whichever // section happens to be active/restored at this point. var dfnSenses = (sections[0] && sections[0].dfn) || []; var dfnSummary = dfnSenses.map(function (s) { return s.mane; }).filter(Boolean).join("; "); var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + sharedValues.lang + ":" + sections[0].pos + ":" + dfnSummary; document.getElementById("wpSummary").value = summary; callback(entry); }); } var continueBtn; function getValuesForStep(stepId) { var fields = $("#wiktku-start-" + stepId + " .wiktku-start-step-field"); var step = steps[stepId]; if (step.keys) { var values = {}; fields.each(function (i, field) { var key = $(field).prevAll(".wiktku-start-step-keyfield").val(); if (key) values[key] = $(field).val(); }); return values; } else if (step.multiple) { return fields.map(function (i) { return $(this).val(); }).get(); } return fields.val(); } function getValues() { var values = {}; $.each(steps, function (stepId) { values[stepId] = getValuesForStep(stepId); }); return values; } function populateMenus(inputs, choices, disabledValues) { if (!disabledValues) disabledValues = {}; var vals = inputs.map(function (i, input) { return $(input).val(); }); inputs.empty(); inputs.append($("<option></option>")); $.each(choices, function (j, choice) { // Append the language code in parentheses so that typing a code // (e.g. "ku") in the search box still finds the language name. var displayText = capitalize(choice[1]); if (choice[2] !== undefined) { // This is a language choice [code, name, sortKey] — show code. displayText = capitalize(choice[1]) + " (" + choice[0] + ")"; } var option = $(mw.html.element("option", { value: choice[0] }, displayText)); if (disabledValues[choice[0]]) option.prop("disabled", true); inputs.append(option); }); inputs.val(function (i) { return vals[i]; }); } /** * Returns a bitmap containing the keys that should be disabled for a key * menu in the given step because they are disabled or already taken by * another key menu. */ function getDisabledKeys(step) { var occupiedKeys = {}; $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").each(function (i, select) { occupiedKeys[$(this).val()] = true; }); if (step.disabledKeys) $.extend(occupiedKeys, step.disabledKeys); return occupiedKeys; } function buildKeyInput(step) { if (!step.keys) return undefined; var input = $(mw.html.element("select", { "class": "wiktku-start-step-keyfield wiktku-start-narrow" })); input.attr("data-placeholder", "Hilbijêre " + step.keyName); if (isMobile) { populateMenus(input, step.keys, getDisabledKeys(step)); // On mobile return the wrapper; the select is inside it. // Change events still fire on the inner select. return wrapNativeSelect(input); } input.on("chosen:showing_dropdown", function (evt, context) { $(this).data("wiktku-defaultValue", $(this).val()); }); input.change(function (evt, context) { var inputs = $("#wiktku-start-" + step.id + " .wiktku-start-step-keyfield").not(this); var oldValue = $(this).data("wiktku-defaultValue"); var newValue = context.selected; inputs.find("option[value='" + oldValue + "']").prop('disabled', false); inputs.find("option[value='" + newValue + "']").prop('disabled', true); inputs.trigger("chosen:updated"); }); populateMenus(input, step.keys, getDisabledKeys(step)); return input; } /** * If the current text field has text and there are no more text fields after * the current text field in the list, add another text field to the list. */ function refreshForTextField(currentInput, step) { currentInput = $(currentInput); var value = currentInput.val(); var item = currentInput.parent(); if (value && !item.next("li").length) { var nextInput = $("<textarea></textarea>") .attr("name", "wiktku-field-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("class", currentInput.attr("class")) .attr("rows", currentInput.attr("rows") || 1); nextInput.on("input", function (evt) { refreshForTextField(evt.target, step); }); var nextKeyInput = buildKeyInput(step); var nextItem = $("<li></li>").append(nextKeyInput).append(nextInput); item.parent().append(nextItem); if (nextKeyInput) nextKeyInput.chosen(chosenOptions); } var canContinue = !continueBtn.prop("disabled"); if ((value && !canContinue) || (!value && canContinue)) { refresh(step); } } function prepareInput(input, step) { if (!input) return; if (step.required) input.prop('required', true); input.change(step, refresh); } /** * Shows and hides all the steps based on whether their prerequisites are met, * and updates placeholders where applicable. */ function refresh(evt) { var values = getValues(); var changedStep = evt && evt.data; var didFocus = false; var canContinue = true; // Re-filter template options in every sense block whenever lang changes. $("#wiktku-start-dfn .wiktku-dfn-tpl-select").each(function () { var fn = $(this).data("updateOptions"); if (typeof fn === "function") fn(); }); // Re-filter pronunciation and etymology template dropdowns when language changes. steps.pron.refreshTplSelect(); steps.etym.refreshTplSelect(); // Sync tr/t sub-fields in every nimûne item to the current language. // tr shown when language needs transliteration; t shown when lang !== "ku". (function () { var lang = values.lang || ""; var showTr = needsTransliteration(lang); var showT = lang && lang !== "ku"; $("#wiktku-start-dfn .wiktku-dfn-nimune-list li.wiktku-dfn-nimune-li").each(function () { var li = $(this); var mainTa = li.find(".wiktku-dfn-nimune-text"); // Ensure the sub-wrapper exists when we need it. var subWrap = li.find(".wiktku-dfn-nimune-sub"); // tr field var trTa = li.find(".wiktku-dfn-nimune-tr"); if (showTr && !trTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } trTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-tr-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-tr") .attr("placeholder", "Transkrîpsiyon…"); subWrap.prepend(trTa); } else if (!showTr && trTa.length) { trTa.remove(); } // t field var tTa = li.find(".wiktku-dfn-nimune-t"); if (showT && !tTa.length) { if (!subWrap.length) { subWrap = $("<div></div>").addClass("wiktku-dfn-nimune-sub"); li.append(subWrap); } tTa = $("<textarea></textarea>") .attr("name", "wiktku-dfn-nimune-t-" + $.now() + "-" + Math.random().toString(36).substr(2, 9)) .attr("rows", 5) .attr("class", "wiktku-dfn-subfield wiktku-dfn-nimune-t") .attr("placeholder", "Tercime (kurmancî)…"); subWrap.append(tTa); } else if (!showT && tTa.length) { tTa.remove(); } // Remove the wrapper if it ended up empty. subWrap = li.find(".wiktku-dfn-nimune-sub"); if (subWrap.length && !subWrap.children().length) subWrap.remove(); }); }()); $.each(steps, function (stepId, step) { if (typeof(step.visible) === "function" && !step.visible(values)) { $("#wiktku-start-" + stepId).slideUp(); // $("#wiktku-start-" + stepId + " .wiktku-start-step-field").val(""); } else { var stepDiv = $("#wiktku-start-" + stepId); if (changedStep !== step && typeof(step.build) === "function") { prepareInput(step.build(stepDiv, values), step); } var input = stepDiv.find(".wiktku-start-step-field"); if (typeof(step.example) === "function") { // .find() above already reaches nested fields (e.g. the dfn // step's mane textareas inside each sense block), so one // assignment covers every step; dfn keeps its own fallback. var exampleText = step.example(values) || (step.id === "dfn" ? "Mane…" : ""); input.attr("placeholder", exampleText); } var didSlideDown; if (!didFocus && stepDiv.css("display") === "none" && step.required) { didSlideDown = function (evt) { input.focus(); }; didFocus = true; } stepDiv.slideDown(didSlideDown); } if (step.required && (values[stepId] === "" || (step.multiple && values[stepId].join("") === ""))) { canContinue = false; } }); continueBtn.button(canContinue ? "enable" : "disable"); } function destroy() { $("#wiktku-start-form, .noafterwizard").slideUp(function () { $(this).remove(); }); $(".noarticletext .nowizard, #editform").slideDown(); $("#ca-edit").removeClass("selected"); $("#ca-wiktku-nowizard").addClass("selected"); } function build() { $(".nowizard, .nowizard .noafterwizard").hide(); var callToAction = $("#wiktku-calltoaction"); var origCallToActionText = callToAction.text(); $(mw.util.addPortletLink("p-views", "#", "Edîtora çavkaniyê veke", "ca-wiktku-nowizard", "Vê rûpelê bi edîtora çavkaniyê çêke", undefined, "#ca-watch")).click(function (evt) { evt.preventDefault(); callToAction.text(origCallToActionText); destroy(); }); callToAction.text(origCallToActionText + " Forma li jêr ji bo çêkirina madeyeke nû bi kar bîne."); var startForm = $("<form id='wiktku-start-form'></form>"); var spinner; // Tab bar for switching between POS sections. var sectionTabsDiv = $("<div id='wiktku-section-tabs'></div>"); startForm.submit(function (evt) { evt.preventDefault(); continueBtn.button("disable"); spinner.show(); getWikitext(function (wikitext) { $("#wpTextbox1").val(wikitext); $("html, body").animate({scrollTop: 0}); callToAction.text("Hindik ma!"); $("#wiktku-preview-container").remove(); destroy(); }); }); $.each(ordered_steps, function (i, step) { var stepDiv = $(mw.html.element("div", { "class": "wiktku-start-step", id: "wiktku-start-" + step.id })); var name = capitalize(step.name); stepDiv.append($(mw.html.element("h3", { "class": "wiktku-start-step-name" }, new mw.html.Raw(mw.html.element("label", { "for": "wiktku-start-" + step.id + "-field" }, name))))); if (step.question_fmt) { var question = step.question_fmt.replace(/\{\{PAGENAME\}\}/g, pageName); stepDiv.append($(mw.html.element("label", { "class": "wiktku-start-step-question", "for": "wiktku-start-" + step.id + "-field" }, question))); if (step.question_br) stepDiv.append($("<br>")); } var input; // Menu if (step.choices) { input = $(mw.html.element("select", { "class": "wiktku-start-step-field", id: "wiktku-start-" + step.id + "-field" })); input.attr("data-placeholder", capitalize(step.name) + " hilbijêre "); populateMenus(input, step.choices); if (step.multiple) input.attr("multiple", true); if (isMobile) { stepDiv.append(wrapNativeSelect(input)); } else { stepDiv.append(input); } } // Custom else if (typeof(step.build) === "function") { input = step.build(stepDiv); } // Text field(s) else { input = $("<textarea></textarea>") .attr("class", "wiktku-start-step-field") .attr("id", "wiktku-start-" + step.id + "-field") .attr("rows", step.rows || 2); if (step.narrow) input.addClass("wiktku-start-narrow"); if (step.multiple) { input.on("input", function (evt) { refreshForTextField(evt.target, step); }); var keyInput = buildKeyInput(step); var list = $(step.ordered ? "<ol></ol>" : "<ul></ul>") .append($("<li></li>").append(keyInput).append(input)); stepDiv.append(list); } else stepDiv.append(input); } prepareInput(input, step); stepDiv.hide(); // Insert tab bar just before the first per-section step. if (step.id === "pos") startForm.append(sectionTabsDiv); startForm.append(stepDiv); }); // ── Section tab helpers ────────────────────────────────────────────── /** Re-render the tab bar to reflect current sections[] and activeSection. */ function renderSectionTabs() { sectionTabsDiv.empty(); // Hide the tab bar entirely until a language is chosen. var lang = getValues().lang || ""; if (!lang) { sectionTabsDiv.hide(); return; } sectionTabsDiv.show(); $.each(sections, function (i) { // Use the stored pos value for the label if available. var posVal = sections[i].pos || ""; var tabLabel = posVal ? capitalize(posVal) : ("Beş " + (i + 1)); var tab = $("<span></span>") .addClass("wiktku-section-tab") .text(tabLabel) .toggleClass("wiktku-tab-active", i === activeSection); (function (idx) { tab.on("click", function () { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); }); }(i)); sectionTabsDiv.append(tab); }); } /** Switch to section idx, saving current first. */ function switchToSection(idx) { if (idx === activeSection) return; saveCurrentSection(); activeSection = idx; restoreSection(sections[activeSection]); refresh(); renderSectionTabs(); } renderSectionTabs(); // Update the active tab's label whenever pos changes. startForm.on("change", "#wiktku-start-pos-field", function () { renderSectionTabs(); }); // Show the tab bar as soon as a language is selected. startForm.on("change", "#wiktku-start-lang-field", function () { renderSectionTabs(); }); var footer = $("<div id='wiktku-start-footer'></div>"); spinner = $(mw.html.element("img", { id: "wiktku-start-spinner", src: "//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif", alt: "Tê barkirin…", title: "Tê barkirin…" })); footer.append(spinner.hide()); continueBtn = $(mw.html.element("button", { id: "wiktku-unhide-editform", type: "submit" }, "Bişîne")); footer.append(continueBtn); // ── Add-section button ─────────────────────────────────────────────── var addSectionBtn = $(mw.html.element("button", { id: "wiktku-add-section", type: "button" }, "+ Beş zêde bike")); addSectionBtn.css("margin-left", "6px"); addSectionBtn.on("click", function () { saveCurrentSection(); sections.push({}); // new empty section activeSection = sections.length - 1; // Clear all per-section fields so the new section starts blank. $.each(PER_SECTION_STEP_IDS, function (_, id) { if (id === "dfn") { var stepDiv = $("#wiktku-start-dfn"); stepDiv.find("ol.wiktku-dfn-list").remove(); steps.dfn.build(stepDiv); return; } if (id === "etym") { $("#wiktku-start-etym .wiktku-etym-wrap").remove(); steps.etym.build($("#wiktku-start-etym")); return; } if (id === "trans") { var transDiv = $("#wiktku-start-trans"); transDiv.find("ul.wiktku-trans-list").remove(); return; } var stepDiv = $("#wiktku-start-" + id); stepDiv.find(".wiktku-start-step-field").val(""); if (!isMobile) stepDiv.find("select.wiktku-start-step-field").trigger("chosen:updated"); }); renderSectionTabs(); refresh(); // Scroll to the tab bar so the user sees the new section. $("html, body").animate({ scrollTop: sectionTabsDiv.offset().top - 20 }, 300); }); footer.append(addSectionBtn); // ── Preview checkboxes ─────────────────────────────────────────────── // Wikitext preview (raw text panel) var previewCheck = $("<input type='checkbox' id='wiktku-preview-toggle'>"); var previewLabel = $("<label for='wiktku-preview-toggle'></label>") .text(" Pêşdîtina wîkîtekstê"); var previewPanel = $("<pre id='wiktku-preview-panel'></pre>").hide(); // Live rendered preview (parsed HTML panel, same logic as AjaxEdit). // Not available on mobile — API polling causes too many problems on small screens. var livePreviewCheck = null; var livePreviewPanel = null; if (!isMobile) { livePreviewCheck = $("<input type='checkbox' id='wiktku-live-preview-toggle'>"); livePreviewPanel = $("<div id='wiktku-live-preview-panel'></div>").hide(); } // Container that holds both panels and switches between stacked / side-by-side. var previewContainer = $("<div id='wiktku-preview-container'></div>"); previewContainer.append(previewPanel); if (!isMobile) previewContainer.append(livePreviewPanel); var previewTimer = null; var livePreviewIntervalId = -1; /** Rebuilds wikitext preview if its checkbox is checked. */ function schedulePreview() { if (!previewCheck.prop("checked")) return; clearTimeout(previewTimer); // Debounce: wait 400 ms after the last keystroke before rebuilding. previewTimer = setTimeout(function () { getWikitext(function (wikitext) { previewPanel.text(wikitext).show(); updatePanelLayout(); }); }, 400); } /** Fetches parsed HTML and populates the live preview panel. */ function loadLivePreview() { getWikitext(function (wikitext) { new mw.Api().parse(wikitext, { title: mw.config.get("wgPageName") }).done(function (html) { livePreviewPanel.html(html).show(); updatePanelLayout(); }); }); } /** Adjusts panel widths depending on which previews are visible. */ function updatePanelLayout() { var wikitextVisible = previewCheck.prop("checked"); var liveVisible = livePreviewCheck && livePreviewCheck.prop("checked"); if (wikitextVisible && liveVisible) { // Side by side — each panel takes roughly half the available width. previewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); livePreviewPanel.css({ "flex": "1 1 45%", "min-width": "280px" }); } else { // Full width for whichever is visible. previewPanel.css({ "flex": "1 1 100%", "min-width": "" }); if (livePreviewPanel) livePreviewPanel.css({ "flex": "1 1 100%", "min-width": "" }); } } previewCheck.on("change", function () { if ($(this).prop("checked")) { schedulePreview(); } else { clearTimeout(previewTimer); previewPanel.hide(); updatePanelLayout(); } }); if (!isMobile) { livePreviewCheck.on("change", function () { if ($(this).prop("checked")) { livePreviewPanel.show(); loadLivePreview(); livePreviewIntervalId = setInterval(loadLivePreview, 500); } else { clearInterval(livePreviewIntervalId); livePreviewIntervalId = -1; livePreviewPanel.hide().empty(); updatePanelLayout(); } }); } // Listen on all input/change events on the form and update both previews. startForm.on("input change", function () { schedulePreview(); }); footer.append($("<span style='margin-left:1em'></span>") .append(previewCheck).append(previewLabel)); if (!isMobile) { var livePreviewLabel = $("<label for='wiktku-live-preview-toggle'></label>") .text(" Pêşdîtina zindî"); footer.append($("<span style='margin-left:1em'></span>") .append(livePreviewCheck).append(livePreviewLabel)); } startForm.append(footer); $("#editform").hide().before(startForm); // Insert preview container (holds both panels) after the form. startForm.after(previewContainer); if (!isMobile) startForm.find("select").chosen(chosenOptions); continueBtn.button(); refresh(); // Zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json bar bike. // Kodên ku bi "-pro" diqedin û navên ku "zimanê destan" tê de heye // tên derxistin. Zimanên xardkirî li serî dimînin, yên din // bi alfabeyê li dû wan tên. // Pinned choices come from MediaWiki:Gadget-start.js/data.json (langChoices), // already loaded into steps.lang.choices before build() runs. var pinnedChoices = steps.lang.choices.slice(); var pinnedCodes = $.map(pinnedChoices, function (choice) { return choice[0]; }); new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-translation_editor.js/ziman.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var zimanData; try { zimanData = JSON.parse(content); } catch (e) { zimanData = {}; } var extraChoices = []; $.each(zimanData, function (code, name) { // Filter: skip proto-language codes and legendary/reconstructed langs. if (/-pro$/i.test(code)) return; if (/ziman[eê]\s+destan/i.test(name)) return; // Skip codes already in the pinned list (they are handled above). if (pinnedCodes.indexOf(code) !== -1) return; // sortKey: bare name without leading "zimanê " for sorting. var sortKey = name.replace(/^ziman[eê]\s+/i, ""); var choice = [code, name, sortKey]; extraChoices.push(choice); langsByCode[code] = choice; }); // Populate langsByCode for pinned choices too. $.each(pinnedChoices, function (i, choice) { // Ensure pinned choices have a sortKey (index 2). if (choice.length < 3) choice[2] = choice[1]; langsByCode[choice[0]] = choice; }); // Sort the extra choices alphabetically by sort key. extraChoices.sort(function (a, b) { return a[2].localeCompare(b[2], userLang); }); // Final list: pinned first, then the rest. var allChoices = pinnedChoices.concat(extraChoices); steps.lang.choices = allChoices; steps.trans.keys = allChoices; var langMenu = $("#wiktku-start-lang-field"); populateMenus(langMenu, steps.lang.choices); langMenu.trigger("chosen:updated"); var transMenus = $("#wiktku-start-trans .wiktku-start-step-keyfield"); populateMenus(transMenus, steps.trans.keys, getDisabledKeys(steps.trans)); transMenus.trigger("chosen:updated"); }); } mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"], function () { // Load metadata, langChoices, posChoices and tplDefs from the companion // data page so they can be updated without touching this script. new mw.Api().get({ action: "query", prop: "revisions", titles: "MediaWiki:Gadget-start.js/data.json", rvprop: "content", rvslots: "main", formatversion: 2 }).then(function (data) { var page = data.query.pages[0]; var content = page && page.revisions && page.revisions[0].slots.main.content; var d; try { d = JSON.parse(content); } catch (e) { d = {}; } // Populate metadata. if (d.metadata) $.extend(metadata, d.metadata); // Populate lang choices (pinned list used by build() → ziman.json loader). if (d.langChoices) steps.lang.choices = d.langChoices; // Populate POS choices. if (d.posChoices) steps.pos.choices = d.posChoices; // Populate template definitions for the dfn sense-block builder. if (d.tplDefs) steps.dfn.tplDefs = d.tplDefs; // Populate pos placeholder examples. if (d.posExamples) steps.dfn.posExamples = d.posExamples; // Populate citation template definitions for the quote widget. if (d.jederDefs) steps.dfn.jederDefs = d.jederDefs; // Populate pronunciation and etymology template insert lists. if (d.pronTpls) { steps.pron.pronTpls = d.pronTpls; steps.pron.refreshTplSelect(); } if (d.etymTpls) { steps.etym.etymTpls = d.etymTpls; steps.etym.refreshTplSelect(); } // Sync trans keys with the (now populated) lang choices. steps.trans.keys = steps.lang.choices; }).always(build); }); }); //</nowiki> 8fo8c6bay2r0zq71qt5igm39ungsqhm Bikarhêner:Wikihez/minerva.js 2 970182 6241655 6033537 2026-07-11T19:42:11Z Wikihez 7344 Rûpel hat valakirin 6241655 javascript text/javascript phoiac9h4m842xq45sp7s6u21eteeq1 Bikarhêner:Wikihez/vector-2022.css 2 1325005 6241656 6241199 2026-07-11T19:42:25Z Wikihez 7344 Rûpel hat valakirin 6241656 css text/css phoiac9h4m842xq45sp7s6u21eteeq1 Bikarhêner:Wikihez/skrîpt/json/loader-settings.json 2 1357332 6241607 6241606 2026-07-11T12:50:14Z Wikihez 7344 Mîhengên Loaderê hatin nûkirin (bi rêza alfabetîk) 6241607 json application/json { "scripts": [ { "key": "etiketCeke", "label": "Etîket Çêke", "src": "Bikarhêner:Wikihez/skrîpt/loader/etîket-çêke.js", "info": "Ji bo şablona {{f}} etîketên nû li Modulê zêde dike.", "disabled": false }, { "key": "mass-delete-category", "label": "Jêbirina bi kom", "src": "Bikarhêner:Wikihez/skrîpt/js/delete.js", "info": "Rûpelên di kategoriyê de bi komî jê dibe (Taybet ji bo adminan)", "disabled": false }, { "key": "kopi-enwikt", "label": "Kopî enwikt", "src": "Bikarhêner:Wikihez/skrîpt/js/kopi-enWikt.js", "info": "Rûpelan ji Wîkîferhenga îngilîzî kopî dike û girêdanên Wîkîdaneyê çêdike.", "disabled": false }, { "key": "test", "label": "test.js", "src": "Bikarhêner:Wikihez/test.js", "info": "Rûpel: Bikarhêner:Wikihez/test.js", "disabled": false } ] } lr2v2zlee3jkxejb3wiij2sjo61s2ge 6241608 6241607 2026-07-11T12:50:54Z Wikihez 7344 Restored revision 6241606 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241608 json application/json { "scripts": [ { "key": "etiketCeke", "label": "Etîket Çêke", "src": "Bikarhêner:Wikihez/skrîpt/loader/etîket-çêke.js", "info": "Ji bo şablona {{f}} etîketên nû li Modulê zêde dike.", "disabled": false }, { "key": "mass-delete-category", "label": "Jêbirina bi kom", "src": "Bikarhêner:Wikihez/skrîpt/js/delete.js", "info": "Rûpelên di kategoriyê de bi komî jê dibe (Taybet ji bo adminan)", "disabled": false }, { "key": "kopi-enwikt", "label": "Kopî enwikt", "src": "Bikarhêner:Wikihez/skrîpt/js/kopi-enWikt.js", "info": "Rûpelan ji Wîkîferhenga îngilîzî kopî dike û girêdanên Wîkîdaneyê çêdike.", "disabled": false } ] } patlcxa5sx0f1rg8oicmxg7siy3qlfj 6241682 6241608 2026-07-11T22:22:32Z Wikihez 7344 Mîhengên Loaderê hatin nûkirin (bi rêza alfabetîk) 6241682 json application/json { "scripts": [ { "key": "etiketCeke", "label": "Etîket Çêke", "src": "Bikarhêner:Wikihez/skrîpt/loader/etîket-çêke.js", "info": "Ji bo şablona {{f}} etîketên nû li Modulê zêde dike.", "disabled": false }, { "key": "formatherf", "label": "formatherf.js", "src": "Bikarhêner:Wikihez/skrîpt/js/formatherf.js", "info": "Rûpel: Bikarhêner:Wikihez/skrîpt/js/formatherf.js", "disabled": false }, { "key": "mass-delete-category", "label": "Jêbirina bi kom", "src": "Bikarhêner:Wikihez/skrîpt/js/delete.js", "info": "Rûpelên di kategoriyê de bi komî jê dibe (Taybet ji bo adminan)", "disabled": false }, { "key": "kopi-enwikt", "label": "Kopî enwikt", "src": "Bikarhêner:Wikihez/skrîpt/js/kopi-enWikt.js", "info": "Rûpelan ji Wîkîferhenga îngilîzî kopî dike û girêdanên Wîkîdaneyê çêdike.", "disabled": false } ] } krr2l1rzbwyzrlwklvywpgz8bv0wx8g 6241684 6241682 2026-07-11T22:25:02Z Wikihez 7344 Mîhengên Loaderê hatin nûkirin (bi rêza alfabetîk) 6241684 json application/json { "scripts": [ { "key": "etiketCeke", "label": "Etîket Çêke", "src": "Bikarhêner:Wikihez/skrîpt/loader/etîket-çêke.js", "info": "Ji bo şablona {{f}} etîketên nû li Modulê zêde dike.", "disabled": false }, { "key": "mass-delete-category", "label": "Jêbirina bi kom", "src": "Bikarhêner:Wikihez/skrîpt/js/delete.js", "info": "Rûpelên di kategoriyê de bi komî jê dibe (Taybet ji bo adminan)", "disabled": false }, { "key": "kopi-enwikt", "label": "Kopî enwikt", "src": "Bikarhêner:Wikihez/skrîpt/js/kopi-enWikt.js", "info": "Rûpelan ji Wîkîferhenga îngilîzî kopî dike û girêdanên Wîkîdaneyê çêdike.", "disabled": false } ] } patlcxa5sx0f1rg8oicmxg7siy3qlfj MediaWiki:Gadget-start.js/data.json 8 1357737 6241609 2026-07-11T13:35:34Z Wikihez 7344 Rûpel bi "{ "metadata": { "aa":{"haswikt":1,"sc":["Latn","Ethi"]}, "ab":{"haswikt":1,"sc":["Cyrl","Latn","Geor"]}, "aer":{"sc":"Latn"}, "af":{"g":["y","p"],"haswikt":1}, "ak":{"haswikt":1}, "akk":{"g":["n","m","n-p","m-p"],"sc":"Xsux"}, "als":{"haswikt":1}, "am":{"g":["n","m","n-p","m-p"],"haswikt":1,"sc":"Ethi"}, "an":{"g":["n","m","n-p","m-p"],"haswikt":1}, "ang":{"alt":1,"g":["n","m","nt","n-p","m-p","nt-p"],"haswikt":1}, "ar"..." hat çêkirin 6241609 json application/json { "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } }, "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "Romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ] }, { "name": "ku-Arab", "langs": [ "ku" ] }, { "name": "ckb-Latn", "langs": [ "ckb" ] }, { "name": "ckb-Arab", "langs": [ "ckb" ] } ] } 6r8x43arbnfrmzvsxt9tnmnvd31kctu 6241613 6241609 2026-07-11T14:03:42Z Wikihez 7344 6241613 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "Romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ] }, { "name": "ku-Arab", "langs": [ "ku" ] }, { "name": "ckb-Latn", "langs": [ "ckb" ] }, { "name": "ckb-Arab", "langs": [ "ckb" ] } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } d3ryfrmlrhq6pdunsjh5orn43juviin 6241616 6241613 2026-07-11T14:25:55Z Wikihez 7344 6241616 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "Romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } r1qiqrpv12gkioy21ek0rrkozgl4d5s 6241635 6241616 2026-07-11T16:25:47Z Wikihez 7344 6241635 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "Romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } qdyeivgm93skizwrrq4x6s6oe3jgf6q 6241638 6241635 2026-07-11T16:43:01Z Wikihez 7344 6241638 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "Romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "kîte", "desc": "Hece şablonê (kurmancî û zimanên din)", "snippet": "{{kîte|LANG|he|ce|le}}" }, { "name": "IPA", "desc": "Navneteweyî alfabe dengî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } r31ce3djto1rg39p0k78fil0p0ygcyl 6241701 6241638 2026-07-11T23:39:32Z Wikihez 7344 6241701 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}" }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } bv0ayt30ndu1qmpwcpheziazz50q82o 6241728 6241701 2026-07-12T10:10:28Z Wikihez 7344 6241728 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}" }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "nt-p", "p" ] }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } oectkla47zhc90l2wgf6xw3w4xnlmfc 6241729 6241728 2026-07-12T10:11:19Z Wikihez 7344 6241729 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}" }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ] }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } f12meh5zq6n6jqjfav9z2795zta3x3k 6241732 6241729 2026-07-12T10:28:52Z Wikihez 7344 6241732 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}", "langs": [ "ku" ], "noLang": true }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } a637o8dkidjbsuem4zzkj62dv8rm8t4 6241733 6241732 2026-07-12T10:32:24Z Wikihez 7344 6241733 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}", "langs": [ "ku" ] }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ] }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } 7axl1h3cxgq0ljgzxic7j7gs0luoc0d 6241738 6241733 2026-07-12T10:49:54Z Wikihez 7344 6241738 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}", "langs": [ "ku" ] }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ] }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } f6crnae6w3agb76qyilxybj4eqkw6ui 6241741 6241738 2026-07-12T10:53:27Z Wikihez 7344 Restored revision 6241732 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]]) 6241741 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}", "langs": [ "ku" ], "noLang": true }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } a637o8dkidjbsuem4zzkj62dv8rm8t4 6241748 6241741 2026-07-12T11:49:32Z Wikihez 7344 6241748 json application/json { "langChoices": [ [ "ku", "kurmancî" ], [ "zza", "zazakî" ], [ "ckb", "soranî" ], [ "sdh", "kurdiya başûrî" ], [ "de", "almanî" ], [ "ar", "erebî" ], [ "fa", "farisî" ], [ "fr", "fransî" ], [ "fi", "fînî" ], [ "en", "îngilîzî" ], [ "sv", "swêdî" ], [ "tr", "tirkî" ] ], "posChoices": [ [ "navdêr", "Navdêr (îsm)" ], [ "lêker", "Lêker (fiîl)" ], [ "rengdêr", "Rengdêr (sifet)" ], [ "hoker", "Hoker (zerf)" ], [ "serenav", "Serenav (îsmê xisûsî)" ], [ "artîkel", "Artîkel" ], [ "baneşan", "Baneşan (nîda)" ], [ "bazinedaçik", "Bazinedaçek" ], [ "cînav", "Cînav (zemîr)" ], [ "daçek", "Daçek (edat)" ], [ "girêdek", "Girêdek" ], [ "gotineke pêşiyan", "Gotineke pêşiyan" ], [ "hejmar", "Hejmar" ], [ "hevok", "Hevok (cimle)" ], [ "îfade", "Îfade" ], [ "kurtenav", "Kurtenav" ], [ "navgir", "Navgir" ], [ "paşdaçek", "Paşdaçek" ], [ "paşgir", "Paşgir" ], [ "pêşdaçek", "Pêşdaçek" ], [ "pêşgir", "Pêşgir" ], [ "pirtik", "Pirtik" ], [ "reh", "Reh" ], [ "sembol", "Sembol" ], [ "tîp", "Tîp (herf)" ] ], "posExamples": { "navdêr": "Kelîmeyên ji bo tiştan (sêv, heywan, qedeh) yan terman (dilşadî, bextiyarî hwd.) di rêzimanê de.", "lêker": "Kelîmeyên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.", "rengdêr": "Kelîmeyên ku wesfa navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.", "hoker": "Kelîmeyên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.", "daçek": "Kelîmeyên ku cih, dem yan hereketê diyar dikin wekî 'di.. de' yan 'ji'.", "cînav": "Kelîmeyên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.", "baneşan": "Kelîmeyên ku hest, deng hwd. îfade dikin wekî 'noşî!' yan 'aferîn'.", "serenav": "Navdêrên ku şexsiyetên ferdî nîşan didin, wek navên kes, cih an organîzasyonan nimûne 'London' yan 'Diyarbekir'.", "gotineke pêşiyan": "Gotinên ku di nav xelkê de bi berbelavî tên bikaranîn bo nimûne 'Serê neêşe ne hewceyî destmalê ye'." }, "tplDefs": [ { "name": "guharto", "langs": null }, { "name": "hevmaneya", "langs": null }, { "name": "awayekî din", "langs": null }, { "name": "pirjimar", "langs": null }, { "name": "romanization", "langs": null }, { "name": "awayê Jacobsonê", "langs": [ "zza" ] }, { "name": "ku-Latn", "langs": [ "ku" ], "noLang": true }, { "name": "ku-Arab", "langs": [ "ku" ], "noLang": true }, { "name": "ckb-Latn", "langs": [ "ckb" ], "noLang": true }, { "name": "ckb-Arab", "langs": [ "ckb" ], "noLang": true } ], "jederDefs": { "jêder-kitêb": { "label": "Kitêb", "fields": [ { "key": "nivîskar", "label": "Nivîskar" }, { "key": "sernav", "label": "Sernav" }, { "key": "sernavê orjînal", "label": "Sernavê orjînal" }, { "key": "terciman", "label": "Terciman" }, { "key": "weşanxane", "label": "Weşanxane" }, { "key": "cih", "label": "Cih" }, { "key": "sal", "label": "Sal" }, { "key": "sala orjînal", "label": "Sala orjînal" }, { "key": "çap", "label": "Çap" }, { "key": "rûpel", "label": "Rûpel" }, { "key": "isbn", "label": "ISBN" }, { "key": "url", "label": "URL" } ] }, "jêder-kovar": { "label": "Kovar", "fields": [ { "key": "nivîskar", "label": "Nivîskar" }, { "key": "nivîskar2", "label": "Nivîskar 2" }, { "key": "sernav", "label": "Sernav" }, { "key": "sernavê orjînal", "label": "Sernavê orjînal" }, { "key": "kovar", "label": "Kovar" }, { "key": "terciman", "label": "Terciman" }, { "key": "weşanxane", "label": "Weşanxane" }, { "key": "cild", "label": "Cild" }, { "key": "hejmar", "label": "Hejmar" }, { "key": "sal", "label": "Sal" }, { "key": "rûpel", "label": "Rûpel" }, { "key": "url", "label": "URL" } ] }, "jêder-malper": { "label": "Malper", "fields": [ { "key": "nivîskar", "label": "Nivîskar" }, { "key": "sernav", "label": "Sernav" }, { "key": "terciman", "label": "Terciman" }, { "key": "malper", "label": "Malper" }, { "key": "url", "label": "URL" }, { "key": "arşîv", "label": "Arşîv URL" }, { "key": "sal", "label": "Sal" } ] } }, "pronTpls": [ { "name": "ku-kîte", "desc": "Şablona hecekirinê ji bo kurmancîz", "snippet": "* {{ku-kîte}}", "langs": [ "ku" ], "noLang": true }, { "name": "kîte", "desc": "Şablona hecekirinê", "snippet": "{{kîte|LANG|he|ce|ki|rin}}" }, { "name": "IPA", "desc": "Alfabeya fonetîk a navmiletî (IPA)", "snippet": "{{IPA|LANG|/…/}}" }, { "name": "hevdeng", "desc": "Hevdeng — gotinên bi heman dengî", "snippet": "{{hevdeng|LANG|…}}" } ], "etymTpls": [ { "name": "ji", "desc": "Ji zimanekî din hatiye — {{ji|sourcelang|lang|peyv|tr=|t=}}", "snippet": "{{ji|SOURCELANG|LANG|…}}" }, { "name": "qertaf", "desc": "Peyvên pêkhatî — {{qertaf|lang|pêşgir|reh}}", "snippet": "{{qertaf|LANG|…|…}}" }, { "name": "q", "desc": "Referans bo rûpelekê — {{q|lang|title}}", "snippet": "{{q|LANG|…}}" }, { "name": "hv", "desc": "Hevreh (cognate) — {{hv|lang|peyv}}", "snippet": "{{hv|LANG|…}}" }, { "name": "mîr", "desc": "Mîras (inherited) — {{mîr|lang|peyv}}", "snippet": "{{mîr|LANG|…}}" }, { "name": "deyn", "desc": "Deyn (borrowed) — {{deyn|lang|peyv}}", "snippet": "{{deyn|LANG|…}}" } ], "metadata": { "aa": { "haswikt": 1, "sc": [ "Latn", "Ethi" ] }, "ab": { "haswikt": 1, "sc": [ "Cyrl", "Latn", "Geor" ] }, "aer": { "sc": "Latn" }, "af": { "g": [ "y", "p" ], "haswikt": 1 }, "ak": { "haswikt": 1 }, "akk": { "g": [ "n", "m", "n-p", "m-p" ], "sc": "Xsux" }, "als": { "haswikt": 1 }, "am": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1, "sc": "Ethi" }, "an": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ang": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "ar": { "g": [ "n", "m", "n-p", "m-p", "p" ], "alt": 1, "haswikt": 1, "sc": "Arab" }, "arc": { "g": [ "n", "m", "n-p", "m-p" ], "sc": [ "Hebr", "Syrc" ] }, "are": {}, "arz": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "sc": "Arab" }, "as": { "haswikt": 1, "sc": "Beng" }, "ast": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "av": { "haswikt": 1 }, "ay": { "haswikt": 1 }, "az": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl", "Arab" ] }, "ba": { "g": [ "y", "p" ], "sc": "Cyrl" }, "bar": {}, "bat-smg": { "g": [ "n", "m", "n-p", "m-p" ] }, "bbl": { "sc": "Geor" }, "be": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "be-x-old": { "sc": "Cyrl" }, "bg": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "bh": { "haswikt": 1, "sc": "Deva" }, "bhb": { "sc": "Deva" }, "bi": { "haswikt": 1 }, "blt": { "sc": "Tavt" }, "bm": { "haswikt": 1, "sc": [ "Latn", "Nkoo", "Arab" ] }, "bn": { "haswikt": 1, "sc": "Beng" }, "bo": { "haswikt": 1, "sc": "Tibt" }, "br": { "g": [ "n", "m" ], "haswikt": 1 }, "ca": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "cdo": { "sc": "Hani" }, "ce": { "sc": "Cyrl" }, "ch": { "haswikt": 1 }, "chr": { "haswikt": 1, "sc": "Cher" }, "cjy": { "sc": "Hani" }, "ckb": { "haswikt": 1, "sc": "Arab", "wsc": "ku-Arab" }, "cmn": { "sc": "Hani", "wiktprefix": "zh" }, "co": { "haswikt": 1 }, "cpx": { "sc": "Hani" }, "cr": { "haswikt": 1, "sc": "Cans" }, "crh": {}, "cs": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "csb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "cu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": [ "Cyrs", "Glag" ] }, "cv": { "sc": "Cyrl" }, "cy": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "czh": { "sc": "Hani" }, "czo": { "sc": "Hani" }, "da": { "g": [ "g", "nt", "g-p", "nt-p", "p" ], "haswikt": 1 }, "dax": {}, "de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "allowCaps": 1 }, "dhg": {}, "djb": {}, "dji": {}, "djr": {}, "dng": { "sc": "Cyrl" }, "dsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "dsx": {}, "duj": {}, "dv": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Thaa" }, "dz": { "haswikt": 1, "sc": "Tibt" }, "el": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "en": { "g": [ "y", "p" ], "haswikt": 1 }, "eo": { "g": [ "y", "p" ], "haswikt": 1 }, "es": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "et": { "g": [ "y", "p" ], "haswikt": 1 }, "ett": { "g": [ "y", "p" ], "sc": "Ital" }, "eu": { "g": [ "y", "p" ], "haswikt": 1 }, "fa": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Arab", "wsc": "fa-Arab" }, "fa-cls": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fa-ira": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "fi": { "g": [ "y", "p" ], "haswikt": 1 }, "fil": {}, "fj": { "haswikt": 1 }, "fo": { "g": [ "n", "m", "nt" ], "haswikt": 1 }, "fr": { "g": [ "n", "m", "mnmane", "n-p", "m-p", "p" ], "haswikt": 1 }, "frm": { "g": [ "n", "m", "n-p", "m-p" ] }, "fro": { "g": [ "n", "m", "n-p", "m-p" ] }, "fur": { "g": [ "n", "m", "n-p", "m-p" ] }, "fy": { "g": [ "g", "nt", "p" ], "haswikt": 1 }, "ga": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "gan": { "sc": "Hani" }, "gd": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gez": { "sc": "Ethi" }, "gl": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "gmw-ecg": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gmy": { "sc": "Linb" }, "gn": { "haswikt": 1 }, "gnn": { "sc": "Latn" }, "got": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "sc": "Goth" }, "grc": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ] }, "gsw": { "g": [ "n", "m", "nt", "p" ], "allowCaps": 1 }, "gu": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Gujr" }, "guf": { "sc": "Latn" }, "gv": { "haswikt": 1 }, "ha": { "haswikt": 1 }, "hak": { "sc": "Hani" }, "har": { "sc": "Ethi" }, "he": { "alt": 1, "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "hi": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Deva" }, "hif": { "sc": [ "Latn", "Deva" ] }, "hit": { "sc": "Xsux" }, "hrx": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "hsb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "hsn": { "sc": "Hani" }, "hu": { "g": [ "y", "p" ], "haswikt": 1 }, "hy": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Armn" }, "ia": { "haswikt": 1 }, "id": { "haswikt": 1 }, "ie": { "haswikt": 1 }, "ik": { "haswikt": 1 }, "ike": { "sc": "Cans" }, "ikt": { "sc": "Cans" }, "io": { "haswikt": 1 }, "is": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "it": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "iu": { "haswikt": 1, "sc": "Cans" }, "ja": { "haswikt": 1, "sc": "Jpan" }, "jay": { "sc": "Latn" }, "jbo": { "haswikt": 1 }, "jv": { "haswikt": 1 }, "ka": { "g": [ "y", "p" ], "haswikt": 1 }, "khb": { "sc": [ "Talu", "Lana", "Thai" ] }, "kjh": { "sc": "Cyrl" }, "kk": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "kkh": { "sc": [ "Lana", "Thai" ] }, "kl": { "haswikt": 1 }, "km": { "haswikt": 1, "sc": "Khmr" }, "kn": { "haswikt": 1, "sc": "Knda" }, "ku": { "g": [ "n", "m", "mn", "n-p", "m-p", "p" ], "wiktprefix": "ku" }, "ko": { "haswikt": 1, "sc": "Kore" }, "krc": { "g": [ "y", "p" ], "sc": "Cyrl" }, "ks": { "haswikt": 1, "sc": [ "Arab", "Deva" ], "wsc": "ks-Arab" }, "kw": { "haswikt": 1 }, "ky": { "haswikt": 1, "g": [ "y", "p" ], "sc": "Cyrl" }, "la": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "lb": { "g": [ "n", "m", "nt", "p" ], "haswikt": 1, "allowCaps": 1 }, "lez": { "sc": "Cyrl" }, "li": { "haswikt": 1 }, "lki": { "wiktprefix": "ku" }, "lld": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lmo": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "ln": { "haswikt": 1 }, "lo": { "haswikt": 1, "sc": "Laoo" }, "lt": { "alt": 1, "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lv": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "lzz": { "sc": "Geor" }, "mg": { "haswikt": 1 }, "mh": { "haswikt": 1 }, "mi": { "g": 0, "haswikt": 1 }, "mk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ml": { "haswikt": 1, "sc": "Mlym" }, "mn": { "g": [ "y", "p" ], "haswikt": 1, "sc": [ "Cyrl", "Mong" ] }, "mnp": { "sc": "Hani" }, "mo": { "haswikt": 1, "sc": "Cyrl" }, "mol": { "sc": "Cyrl" }, "mr": { "g": [ "n", "m", "nt" ], "haswikt": 1, "sc": "Deva" }, "ms": { "haswikt": 1, "sc": [ "Latn", "Arab" ] }, "mt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "mwp": { "sc": "Latn" }, "my": { "haswikt": 1, "sc": "Mymr" }, "na": { "haswikt": 1 }, "nah": { "haswikt": 1 }, "nan": { "wiktprefix": "zh-min-nan", "sc": "Hani" }, "nb": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "wiktprefix": "no" }, "nds-de": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "nds-nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "ne": { "haswikt": 1, "sc": "Deva" }, "nl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nn": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "no": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1 }, "nod": { "sc": "Lana" }, "non": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "oc": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "om": { "haswikt": 1 }, "or": { "haswikt": 1, "sc": "Orya" }, "orv": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrs" }, "osc": { "sc": "Ital" }, "ota": { "g": [ "y", "p" ], "sc": "Arab", "wsc": "ota-Arab" }, "pa": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": [ "Guru", "Arab" ] }, "pdt": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "nds" }, "peo": { "sc": "Xpeo" }, "phn": { "sc": "Phnx" }, "pi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1 }, "pjt": { "sc": "Latn" }, "pl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "pms": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "pox": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "împf", "pf" ] }, "prs": { "wiktprefix": "fa", "sc": "Arab", "wsc": "fa-Arab" }, "ps": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ps-Arab" }, "pt": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1 }, "qu": { "haswikt": 1 }, "rgn": { "g": [ "n", "m", "n-p", "m-p" ] }, "rit": { "sc": "Latn" }, "rm": { "g": [ "n", "m" ], "haswikt": 1 }, "rn": { "haswikt": 1 }, "ro": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "roa-rup": { "haswikt": 1 }, "ru": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "rue": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "sc": "Cyrl" }, "ruo": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rup": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "wiktprefix": "roa-rup" }, "ruq": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "rw": { "haswikt": 1 }, "sa": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ], "haswikt": 1, "sc": "Deva" }, "sah": { "sc": "Cyrl" }, "sc": { "haswikt": 1 }, "scn": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "sco": { "sc": "Latn" }, "sd": { "haswikt": 1, "sc": "Arab", "wsc": "sd-Arab" }, "sdh": { "wiktprefix": "ku" }, "sg": { "haswikt": 1 }, "sh": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": [ "Latn", "Cyrl" ] }, "si": { "haswikt": 1, "sc": "Sinh" }, "simple": { "haswikt": 1 }, "sk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sl": { "alt": 1, "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1 }, "sm": { "haswikt": 1 }, "sn": { "haswikt": 1 }, "so": { "haswikt": 1 }, "spx": { "sc": "Ital" }, "sq": { "g": [ "n", "m" ], "haswikt": 1 }, "ss": { "haswikt": 1 }, "st": { "haswikt": 1 }, "su": { "haswikt": 1 }, "sux": { "sc": "Xsux" }, "sv": { "g": [ "g", "nt", "g-p", "nt-p" ], "haswikt": 1 }, "sva": { "sc": "Geor" }, "sw": { "nclass": 1, "haswikt": 1 }, "syc": { "sc": "Syrc" }, "syr": { "sc": "Syrc" }, "szl": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ] }, "ta": { "haswikt": 1, "sc": "Taml" }, "tdd": { "sc": "Tale" }, "te": { "haswikt": 1, "sc": "Telu" }, "tg": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Cyrl" }, "th": { "haswikt": 1, "sc": "Thai" }, "ti": { "haswikt": 1, "sc": "Ethi" }, "tig": { "sc": "Ethi" }, "tiw": { "sc": "Latn" }, "tk": { "g": [ "y", "p" ], "haswikt": 1 }, "tl": { "haswikt": 1, "sc": [ "Latn", "Tglg" ] }, "tmr": { "sc": "Hebr" }, "tn": { "haswikt": 1 }, "to": { "haswikt": 1 }, "tpi": { "haswikt": 1 }, "tr": { "g": [ "y", "p" ], "alt": 1, "haswikt": 1 }, "ts": { "haswikt": 1 }, "tt": { "g": [ "y", "p" ], "haswikt": 1 }, "tts": { "sc": "Thai" }, "tw": { "haswikt": 1 }, "udi": { "sc": [ "Cyrl", "Latn", "Armn", "Geor" ] }, "ug": { "g": [ "y", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ug-Arab" }, "uga": { "sc": "Ugar" }, "uk": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p", "împf", "pf" ], "haswikt": 1, "sc": "Cyrl" }, "ulk": { "sc": "Latn" }, "ur": { "g": [ "n", "m", "n-p", "m-p", "p" ], "haswikt": 1, "sc": "Arab", "wsc": "ur-Arab" }, "uz": { "g": [ "y", "p" ], "haswikt": 1 }, "vec": { "g": [ "n", "m", "n-p", "m-p" ], "haswikt": 1 }, "vi": { "haswikt": 1 }, "vls": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p" ] }, "vo": { "haswikt": 1 }, "wa": { "haswikt": 1 }, "wbp": { "sc": "Latn" }, "wo": { "haswikt": 1 }, "wuu": { "sc": "Hani" }, "xae": { "sc": "Ital" }, "xcr": { "sc": "Cari" }, "xfa": { "sc": "Ital" }, "xh": { "alt": 1, "nclass": 1, "haswikt": 1 }, "xlc": { "sc": "Lyci" }, "xld": { "sc": "Lydi" }, "xlu": { "sc": "Xsux" }, "xmf": { "sc": "Geor" }, "xno": { "g": [ "n", "m", "n-p", "m-p" ] }, "xrr": { "sc": "Ital" }, "xst": { "sc": "Ethi" }, "xum": { "sc": "Ital" }, "xve": { "sc": "Ital" }, "xvo": { "sc": "Ital" }, "yi": { "g": [ "n", "m", "nt", "n-p", "m-p", "nt-p", "p" ], "haswikt": 1, "sc": "Hebr" }, "yo": { "haswikt": 1 }, "yua": { "g": [ "y", "p" ], "alt": 1 }, "yue": { "sc": "Hani" }, "za": { "haswikt": 1, "sc": "Latn" }, "zh-classical": { "sc": "Hani" }, "zh-min-nan": { "haswikt": 1 }, "zh-yue": { "sc": "Hani" }, "zu": { "alt": 1, "nclass": 1, "haswikt": 1 } } } htz4ghrc7w1r1hve6jk1wokbischilz Kategorî:Maneyên bêçavkanî 14 1357738 6241651 2026-07-11T18:57:09Z Wikihez 7344 Rûpel bi "[[Kategorî:Madeyên bêçavkanî|!]]" hat çêkirin 6241651 wikitext text/x-wiki [[Kategorî:Madeyên bêçavkanî|!]] ncob6stlso25vf8z9g7600qotyikdaf Bikarhêner:Wikihez/skrîpt/js/formatherf.js 2 1357739 6241681 2026-07-11T22:21:46Z Wikihez 7344 Rûpel bi "/** * Nav: TextTransformGadget * Kar: Guhertina herfên nivîsê (Lowercase, Uppercase, Sentence, Title Case) * Ziman: ku, tr, en */ (function ($) { var messages = { ku: { label: "Format", lowercase: "Hemû herf biçûk (abc)", uppercase: "Hemû herf mezin (ABC)", sentence: "Herfa destpêkê mezin (Abc)", title: "Herfên sernavê (Abc Abc)", select_action: "Guhertina herfan"..." hat çêkirin 6241681 javascript text/javascript /** * Nav: TextTransformGadget * Kar: Guhertina herfên nivîsê (Lowercase, Uppercase, Sentence, Title Case) * Ziman: ku, tr, en */ (function ($) { var messages = { ku: { label: "Format", lowercase: "Hemû herf biçûk (abc)", uppercase: "Hemû herf mezin (ABC)", sentence: "Herfa destpêkê mezin (Abc)", title: "Herfên sernavê (Abc Abc)", select_action: "Guhertina herfan" }, tr: { label: "Biçim", lowercase: "Hepsini küçük yap (abc)", uppercase: "Hepsini büyük yap (ABC)", sentence: "Sadece ilk harfi büyük yap (Abc)", title: "Başlık formatı (Abc Abc)", select_action: "Harf değişimini seç" }, en: { label: "Format", lowercase: "Lowercase (abc)", uppercase: "Uppercase (ABC)", sentence: "Sentence case (Abc)", title: "Title case (Abc Abc)", select_action: "Select text transform" } }; var userLang = mw.config.get("wgUserLanguage"); var lang = messages[userLang] ? userLang : (messages[userLang.split('-')[0]] ? userLang.split('-')[0] : 'en'); var msg = messages[lang]; // Peyvên ku di "Title Case" de herfên wan nabin mezin var minorWords = [ "û", "ji", "bi", "de", "di", "li", "re", "ve", "tê", "jî", "jê", "ku", "bo", "ser", "ber", // Kurdî "ve", "ile", "de", "da", "ki", "mı", "mi", "mu", "mü", "ama", "veya", "için", // Tirkî "and", "or", "but", "a", "an", "the", "in", "on", "at", "to", "for", "of", "with" // Îngilîzî ]; var transformText = function (text, type) { if (!text) return text; switch (type) { case 'lowercase': return text.replace(/I/g, 'ı').replace(/İ/g, 'i').toLowerCase(); case 'uppercase': return text.replace(/i/g, 'İ').replace(/ı/g, 'I').toUpperCase(); case 'sentence': var first = text.charAt(0); if (first === 'i') first = 'İ'; else first = first.toUpperCase(); return first + text.slice(1).toLowerCase(); case 'title': var words = text.split(/\s+/); var result = words.map(function (word, index) { var lowerWord = word.toLowerCase(); if (index > 0 && minorWords.indexOf(lowerWord) !== -1) { return lowerWord; } var firstChar = word.charAt(0); if (firstChar === 'i') firstChar = 'İ'; else firstChar = firstChar.toUpperCase(); return firstChar + word.slice(1).toLowerCase(); }); return result.join(' '); default: return text; } }; var addTransformTool = function () { mw.loader.using('ext.wikiEditor', function () { $('#wpTextbox1').on('wikiEditor-toolbar-buildSection-main', function (evt, section) { section.groups.insert.tools.texttransform = { type: 'select', label: msg.label, list: { 'lowercase': { label: msg.lowercase }, 'uppercase': { label: msg.uppercase }, 'sentence': { label: msg.sentence }, 'title': { label: msg.title } }, action: { type: 'callback', execute: function (context) { var type = $(this).data('action').replace('texttransform-', ''); var selection = $("#wpTextbox1").textSelection('getSelection'); if (!selection) return; var newText = transformText(selection, type); $("#wpTextbox1").textSelection('encapsulateSelection', { peri: newText, replace: true }); } } }; }); }); }; $(document).ready(addTransformTool); })(jQuery); aqzmt4g9aw61qlelclt327t9oqsnkil 6241686 6241681 2026-07-11T22:27:22Z Wikihez 7344 6241686 javascript text/javascript (function ($) { var messages = { ku: { label: "Format", lowercase: "abc", uppercase: "ABC", sentence: "Abc", title: "Abc Abc" }, tr: { label: "Biçim", lowercase: "abc", uppercase: "ABC", sentence: "Abc", title: "Abc Abc" }, en: { label: "Format", lowercase: "abc", uppercase: "ABC", sentence: "Abc", title: "Abc Abc" } }; var userLang = mw.config.get("wgUserLanguage"); var lang = messages[userLang] ? userLang : 'ku'; var msg = messages[lang]; var minorWords = ["û", "ji", "bi", "de", "di", "li", "re", "ve", "tê", "jî", "jê", "ku", "bo", "ser", "ber", "and", "or", "the", "in", "of"]; var transformText = function (text, type) { if (!text) return text; switch (type) { case 'lowercase': return text.replace(/I/g, 'ı').replace(/İ/g, 'i').toLowerCase(); case 'uppercase': return text.replace(/i/g, 'İ').replace(/ı/g, 'I').toUpperCase(); case 'sentence': return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase(); case 'title': return text.split(/\s+/).map(function (word, index) { var lower = word.toLowerCase(); if (index > 0 && minorWords.indexOf(lower) !== -1) return lower; return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(' '); default: return text; } }; var applyTransform = function(type) { var $box = $('#wpTextbox1'); var selection = $box.textSelection('getSelection'); if (selection) { $box.textSelection('encapsulateSelection', { peri: transformText(selection, type), replace: true }); } }; // 1. Ji bo Desktop (WikiEditor) mw.loader.using('ext.wikiEditor', function () { $('#wpTextbox1').on('wikiEditor-toolbar-buildSection-main', function (evt, section) { section.groups.insert.tools.texttransform = { type: 'select', label: msg.label, list: { 'lowercase': { label: msg.lowercase }, 'uppercase': { label: msg.uppercase }, 'sentence': { label: msg.sentence }, 'title': { label: msg.title } }, action: { type: 'callback', execute: function () { applyTransform($(this).data('action').replace('texttransform-', '')); } } }; }); }); // 2. Ji bo Mobîl (Menuya hêsan li ser qutîkê) $(document).ready(function() { if ($('#wpTextbox1').length && !$('.wikiEditor-ui').length) { var $mobileTools = $('<div id="mobile-format-tools" style="margin-bottom:5px;"></div>'); $mobileTools.append('<span>' + msg.label + ': </span>'); ['lowercase', 'uppercase', 'sentence', 'title'].forEach(function(type) { var $btn = $('<button type="button" style="margin-right:5px; padding:2px 5px; font-size:12px;">' + msg[type] + '</button>'); $btn.on('click', function(e) { e.preventDefault(); applyTransform(type); }); $mobileTools.append($btn); }); $('#wpTextbox1').before($mobileTools); } }); })(jQuery); 9ok2oj7vwalm9pb13x2mk43syh4ghqn dîwançe 0 1357740 6241696 2026-07-11T23:23:10Z Wikihez 7344 ([[Mediawiki:Gadget-start.js|WF:Nû]]) +ku:navdêr:Dîwana şiîran a biçûk 6241696 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|dîwançe|mê}} {{navdêr|ku|c=m}} # [[dîwana|Dîwana]] [[şiîran]] a [[biçûk]]. #: {{jêder|ku|jg=Emê jî li ser şexsiyet û '''dîwançeya''' yek ji van kesan, li ser Mela Ebdullahê Qursincî bisekinin.|Dîwançeya}} ==== Etîmolojî ==== Ji {{qertaf|ku|dîwan|-çe}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W|tr|divançe}} {{werger-bin}} hgqg6mywwbmh64421hb1kv8yli1grti 6241697 6241696 2026-07-11T23:27:25Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241697 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|dîwançe|mê}} {{navdêr|ku|c=m}} # [[dîwana|Dîwana]] [[şiîran]] a [[biçûk]]. #: {{jêder-kitêb|ku|jg=Emê jî li ser şexsiyet û '''dîwançeya''' yek ji van kesan, li ser Mela Ebdullahê Qursincî bisekinin.|nivîskar=Mahmut Durmuş|sernav=DÎWANÇEYA MELA EBDULLAHÊ Qursincî (LÊKOLÎN & METN)|sal=2019}} ==== Etîmolojî ==== Ji {{qertaf|ku|dîwan|-çe}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W|tr|divançe}} {{werger-bin}} 0mqhe9sh5nnrgi3fxecsf1l6itnel7m 6241698 6241697 2026-07-11T23:28:07Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241698 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|dîwançe|mê}} {{navdêr|ku|c=m}} # [[dîwana|Dîwana]] [[şiîran]] a [[biçûk]]. #* {{jêder-kitêb|ku|jg=Emê jî li ser şexsiyet û '''dîwançeya''' yek ji van kesan, li ser Mela Ebdullahê Qursincî bisekinin.|nivîskar=Mahmut Durmuş|sernav=DÎWANÇEYA MELA EBDULLAHÊ Qursincî (LÊKOLÎN & METN)|sal=2019}} ==== Etîmolojî ==== Ji {{qertaf|ku|dîwan|-çe}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W|tr|divançe}} {{werger-bin}} ate39nzc4qafon9ppj8lc7mjlp9z78j 6241699 6241698 2026-07-11T23:28:30Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241699 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|dîwançe|mê}} {{navdêr|ku|c=m}} # {{e|ku|edebiyat|şiîr}} [[dîwana|Dîwana]] [[şiîran]] a [[biçûk]]. #* {{jêder-kitêb|ku|jg=Emê jî li ser şexsiyet û '''dîwançeya''' yek ji van kesan, li ser Mela Ebdullahê Qursincî bisekinin.|nivîskar=Mahmut Durmuş|sernav=DÎWANÇEYA MELA EBDULLAHÊ Qursincî (LÊKOLÎN & METN)|sal=2019}} ==== Etîmolojî ==== Ji {{qertaf|ku|dîwan|-çe}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W|tr|divançe}} {{werger-bin}} fee5yzwgj94bs9brlx7breokfyz0cwj 6241709 6241699 2026-07-11T23:48:14Z Balyozbot 7867 Sererastkirin/rêzkirina şablonên {{[[Şablon:W-|W-]]}}, {{[[Şablon:W+|W+]]}} ([[User:Balyozxane/updateW.py|updateW]]) 6241709 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|dîwançe|mê}} {{navdêr|ku|c=m}} # {{e|ku|edebiyat|şiîr}} [[dîwana|Dîwana]] [[şiîran]] a [[biçûk]]. #* {{jêder-kitêb|ku|jg=Emê jî li ser şexsiyet û '''dîwançeya''' yek ji van kesan, li ser Mela Ebdullahê Qursincî bisekinin.|nivîskar=Mahmut Durmuş|sernav=DÎWANÇEYA MELA EBDULLAHÊ Qursincî (LÊKOLÎN & METN)|sal=2019}} ==== Etîmolojî ==== Ji {{qertaf|ku|dîwan|-çe}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W+|tr|divançe}} {{werger-bin}} 57jtjvalgigjbp6cp3rgi4xlwgx22gl şifêr 0 1357741 6241702 2026-07-11T23:40:49Z Wikihez 7344 ([[Mediawiki:Gadget-start.js|WF:Nû]]) +ku:navdêr: 6241702 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|c=nt}} # {{guharto|ku|şofêr}} 314ba0ktz92yx1jjqj1qvql2klcxduw 6241703 6241702 2026-07-11T23:41:02Z Wikihez 7344 /* Navdêr */ 6241703 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|c=mn}} # {{guharto|ku|şofêr}} avm5iuififfkf86s6j1ecph358gb88i lînguîstîk 0 1357742 6241711 2026-07-11T23:56:51Z Wikihez 7344 ([[Mediawiki:Gadget-start.js|WF:Nû]]) +ku:navdêr: 6241711 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|lînguîstîk|mê}} {{navdêr|ku|c=m}} # {{guharto|ku|lenguîstîk}} bl0acbi1pketrjhv40n4p9z71a30iyr bursiyer 0 1357743 6241713 2026-07-12T00:14:23Z Wikihez 7344 ([[Mediawiki:Gadget-start.js|WF:Nû]]) +ku:navdêr:Telebeyê ku xwedî bursekê ji unîversîte, weqf and dewletekê ye. 6241713 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|c=nt}} # [[Telebeyê]] ku [[xwedî]] [[burs]]ekê [[ji]] [[unîversîte]], [[weqf]] [[an]] [[dewlet]]ekê ye. #* {{bênimûne|ku}} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W|en|scholar}}, {{W|en|scholarship holder}} * {{Z|tr}}: {{W|tr|bursiyer}} {{werger-bin}} tutz3mbemm7lsnm30uktrf623ti7xc0 6241714 6241713 2026-07-12T00:15:00Z Wikihez 7344 /* Navdêr */ 6241714 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|bursiyer|mê û nêr}} {{navdêr|ku|c=mn}} # [[telebe|Telebeyê]] ku [[xwedî]] [[burs]]ekê [[ji]] [[unîversîte]], [[weqf]] [[an]] [[dewlet]]ekê ye. #* {{bênimûne|ku}} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|en}}: {{W|en|scholar}}, {{W|en|scholarship holder}} * {{Z|tr}}: {{W|tr|bursiyer}} {{werger-bin}} bpyx1t9jjihzs2uzl3270tqt28stowu 6241717 6241714 2026-07-12T00:17:53Z Wikihez 7344 [[Bikarhêner:Wikihez/wergerîne.js|Wergerîne]] ji [[en:scholarship holder]] 6241717 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|bursiyer|mê û nêr}} {{navdêr|ku|c=mn}} # [[telebe|Telebeyê]] ku [[xwedî]] [[burs]]ekê [[ji]] [[unîversîte]], [[weqf]] [[an]] [[dewlet]]ekê ye. #* {{bênimûne|ku}} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser}} * {{Z|fr}}: {{W+|fr|boursier|}} * {{Z|en}}: {{W+|en|scholarship holder}} {{W+|en|scholar}} * {{Z|pt}}: {{W-|pt|bolsista|}} * {{Z|es}}: {{W+|es|becario|}}, {{W+|es|becado|}} * {{Z|tr}}: {{W-|tr|bursiyer}} {{werger-bin}} :{{werger çavkanî|en|scholarship holder|beş=Ev qismê Wergerê|oldid=91120755}} tjm6byp1ixp5yfngrwf0glelqcyhjza 6241718 6241717 2026-07-12T00:18:15Z Wikihez 7344 Werger: sernav: "kesê ku burs werdigire" (bi alîkarî) 6241718 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|bursiyer|mê û nêr}} {{navdêr|ku|c=mn}} # [[telebe|Telebeyê]] ku [[xwedî]] [[burs]]ekê [[ji]] [[unîversîte]], [[weqf]] [[an]] [[dewlet]]ekê ye. #* {{bênimûne|ku}} ==== Etîmolojî ==== {{bêetîmolojî}} ==== Werger ==== {{werger-ser|kesê ku burs werdigire}} * {{Z|fr}}: {{W+|fr|boursier|}} * {{Z|en}}: {{W+|en|scholarship holder}} {{W+|en|scholar}} * {{Z|pt}}: {{W-|pt|bolsista|}} * {{Z|es}}: {{W+|es|becario|}}, {{W+|es|becado|}} * {{Z|tr}}: {{W-|tr|bursiyer}} {{werger-bin}} :{{werger çavkanî|en|scholarship holder|beş=Ev qismê Wergerê|oldid=91120755}} dxra8q8e1y3xpmtdv7zr4tm51nelpwk 6241722 6241718 2026-07-12T00:59:20Z Wikihez 7344 /* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re 6241722 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{ku-tewîn-nav|bursiyer|mê û nêr}} {{navdêr|ku|c=mn}} # [[telebe|Telebeyê]] ku [[xwedî]] [[burs]]ekê [[ji]] [[unîversîte]], [[weqf]] [[an]] [[dewlet]]ekê ye. #* {{bênimûne|ku}} ==== Etîmolojî ==== Ji {{ji|fr|ku|boursier}}. ==== Werger ==== {{werger-ser|kesê ku burs werdigire}} * {{Z|fr}}: {{W+|fr|boursier|}} * {{Z|en}}: {{W+|en|scholarship holder}} {{W+|en|scholar}} * {{Z|pt}}: {{W-|pt|bolsista|}} * {{Z|es}}: {{W+|es|becario|}}, {{W+|es|becado|}} * {{Z|tr}}: {{W-|tr|bursiyer}} {{werger-bin}} :{{werger çavkanî|en|scholarship holder|beş=Ev qismê Wergerê|oldid=91120755}} au3i2du6zy7z95zh3mjhtsdpfymyey5 scholarship holder 0 1357744 6241715 2026-07-12T00:15:24Z Wikihez 7344 ([[Bikarhêner:Wikihez/newentrywiz.js|NEC]]) +en:navdêr: Bi [[Bikarhêner:Wikihez/CreateTranslation.js|amûrê]] ji wergerên [[bursiyer]]: 6241715 wikitext text/x-wiki == {{ziman|en}} == === Navdêr === {{en-navdêr}} # [[bursiyer]] 18i2e4yx1b3mj7q6qm21nd9lw6tb36a 6241716 6241715 2026-07-12T00:16:00Z Wikihez 7344 /* {{ziman|en}} */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: Ji [[en:scholarship holder|en.wikt]] 6241716 wikitext text/x-wiki == {{ziman|en}} == === Navdêr === {{en-navdêr}} # [[bursiyer]] #: {{hevmane|en||scholarship recipient|grant recipient|grant holder|scholarship beneficiary|grantee}} ==== Têkildar ==== * {{g|en|scholar}} * {{g|en|scholarly}} * {{g|en|scholarship}} h1m3daii9he06du9c69iravb8xk74bg Şablon:koordîne 10 1357745 6241727 2026-07-12T10:08:20Z Wikihez 7344 Ji bo [[Şablon:termên koordîne]] hat beralîkirin 6241727 wikitext text/x-wiki #BERALÎKIRIN [[Şablon:termên koordîne]] 3226zx2ohrzwyf0dpo3d1063hut8942 Gotûbêja bikarhêner:Kewkûrk 3 1357746 6241750 2026-07-12T11:56:11Z Wikihez 7344 xêrhatin lê zêde kir 6241750 wikitext text/x-wiki {{bixêrhatin}} == Xêrhatin == Merheba bikarhênera/ê me ya/ê hêja: ''Kewkûrk'', Bi xêr hatî ferhenga kurdî-kurdî WÎKÎFERHENGê {{=)}} Em hêvîdar in ku tu jî di avakirina vê ferhengê de alîkariya me bikî. Eger pirsên te hebin, dikarî li ser [[WF:Dîwan]]ê bipirsî. Xebatxweş. :—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:56, 12 tîrmeh 2026 (UTC) :Not: Min guhartina te ya Alîkarî:Nivîsin betal kir ji ber ku ev cih xelet e. Divê li [[dêrtin]] binivîsî.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:56, 12 tîrmeh 2026 (UTC) ov3xkpbyi7ydw31trtv6mreodiinwce 6241751 6241750 2026-07-12T11:57:23Z Kewkûrk 15130 /* Xêrhatin */ Bersiv 6241751 wikitext text/x-wiki {{bixêrhatin}} == Xêrhatin == Merheba bikarhênera/ê me ya/ê hêja: ''Kewkûrk'', Bi xêr hatî ferhenga kurdî-kurdî WÎKÎFERHENGê {{=)}} Em hêvîdar in ku tu jî di avakirina vê ferhengê de alîkariya me bikî. Eger pirsên te hebin, dikarî li ser [[WF:Dîwan]]ê bipirsî. Xebatxweş. :—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:56, 12 tîrmeh 2026 (UTC) :Not: Min guhartina te ya Alîkarî:Nivîsin betal kir ji ber ku ev cih xelet e. Divê li [[dêrtin]] binivîsî.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:56, 12 tîrmeh 2026 (UTC) ::spas bira,min xeletî kir. Ez lêborînê dixwazim. [[Bikarhêner:Kewkûrk|Kewkûrk]] ([[Gotûbêja bikarhêner:Kewkûrk#top|gotûbêj]]) 11:57, 12 tîrmeh 2026 (UTC) ffrmmgjd2ifj0g255zl4c17fc1no1y9