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
aborî
0
5726
6241589
6233303
2026-07-10T21:06:45Z
InternetArchiveBot
8979
Rescuing 1 sources and tagging 0 as dead.) #IABot (v2.0.9.5
6241589
wikitext
text/x-wiki
== {{ziman|ku}} ==
=== Bilêvkirin ===
* {{ku-IPA}}
* {{deng|ku|LL-Q36163_(kmr)-Key Mîrza-aborî.wav|Deng|Wan}}
* {{ku-kîte}}
=== Navdêr ===
{{ku-tewîn-nav|aborî|mê}}
[[Wêne:Billets_de_5000.jpg|thumb|[[pare|Pare]] di aboriyê de giring in.]]
{{navdêr|ku|z=m}}
# [[karûbar|Karûbar]]ên [[kirîn]] û [[firotin]]ê yên [[tevahî|tevahiya]] [[civak]]ekê.
#: {{hevmane|ku|ekonomî|iqtisad}}
#: {{mk|ku|'''Aboriya''' wî welatî gelek pêş ketiye.}}
# [[hêz|Hêz]]a kesekî ya pê bikare tiştan [[kirîn|bikire]].
#* {{jêder|ku|jêgirtin=Ji ber ko rewşa mala Sîdar ya '''aborî''' ne baş bû; wî him di daîreyeke dewletê de kar dikir û him jî unîversîteya xwe dixwend."|{{Jêgirtin/Bûbê Eser/Gardiyan/2002}}}}
# [[bikaranîn|Bikaranîn]]a [[saman]] û [[sermiyan]]î bi awayekî wisa ku zêde xerc nebe lê dîsa jî [[mifa]]yek baş jê bêt wergirtin.
#* {{bêmînak|ku}}
# [[zanist|Zanist]]a [[aborî|aboriyê]].
#: {{hevmane|ku|aborînasî}}
#* {{bêmînak|ku}}
==== Bi alfabeyên din ====
* {{ku-ar|ئابۆری}}
* {{ku-kr|абори}}
==== Herwiha ====
* {{g|ku|abûrî}}
* {{g|ku|eborî}}
* {{g|ku|ebûrî}}
==== Bide ber ====
* {{g|ku|dara}}
==== Jê ====
* {{g|ku|aborînas}}
* {{g|ku|aborînasî}}
* {{g|ku|aborîvan}}
* {{g|ku|aborîvanî}}
* {{g|ku|aborîzan}}
* {{g|ku|aborîzanî}}
==== Etîmolojî ====
Hevreha soranî {{g|ckb|ئابووری}}, ji {{ji|sem}}, bo nimûne ji {{ji|arc|ku|ܥܒܘܪܐ}} (ibûra / ivûra: [[berhem]], [[ber]], [[dexlûdan]], [[xurak]], [[xwarin]], aborî, [[deramet]]) [https://web.archive.org/web/20210803192702/http://cal.huc.edu/searchroots.php?pos=N&lemma=(br], hevreha akadî [[𒂘]] (ebūru [BURU<sup>14</sup>]: [[xerman]])[http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=eb%26%23363%3Bru&language=rawakkadian], {{hv|he|עבור}} (abor: [[ji ber]], [[bermayî]], [[berhem]]), têkilî erebî {{g|ar|عبر}} ('ebere: [[borîn]], [[derbas]] bûn). Ji eynî rehî belkî herwiha: [[borîn]] / [[buhirîn]] û [[borandin]] / [[buhirandin]] yên kurdî.
==== Werger ====
{{werger-ser|iqtisad, birêvebirina serwet û dahatên civakekê}}
* {{Z|de}}: {{W+|de|Ökonomie|m}}
* {{Z|zgh}}: {{W-|zgh|ⵜⴰⴷⵎⵙⴰ|m}}
* {{Z|be}}: {{W-|be|экано́мія|m}}
* {{Z|bg}}: {{W+|bg|иконо́мика|m}}, {{W+|bg|стопа́нство|nt}}
* {{Z|bua}}: {{W-|bua|ажахы}}
* {{Z|zh}}:
*: {{Z|cmn}}: {{W+|cmn|經濟}}
* {{Z|da}}: {{W+|da|økonomi|g}}, {{W-|da|husholdning|g}}, {{W-|da|husholdning|g}}
* {{Z|ar}}: {{W+|ar|اِقْتِصاد|n}}
*: {{Z|acw}}: {{W-|acw|اِقْتِصاد|n|tr=igtiṣād}}
* {{Z|eo}}: {{W-|eo|ekonomio}}
* {{Z|fi}}: {{W+|fi|talous}}
* {{Z|ff}}:
*: Adlamî: {{W-|ff|𞤬𞤢𞤺𞥆𞤵𞤣𞤵}}
*: Latînî: {{W-|ff|faggudu}}
* {{Z|gd}}: {{W-|gd|eaconomaidh|n}}
* {{Z|nl}}: {{W+|nl|economie|m}}
* {{Z|io}}: {{W+|io|ekonomio}}
* {{Z|en}}: {{W+|en|economy}}
* {{Z|ga}}: {{W-|ga|barainneacht|m}}
* {{Z|it}}: {{W+|it|economia|m}}
* {{Z|is}}: {{W-|is|hagur|n}}
* {{Z|ja}}: {{W+|ja|経済|tr=けいざい, keizai}}
* {{Z|ca}}: {{W+|ca|economia|m}}
* {{Z|ko}}: {{W+|ko|경제}}
* {{Z|lv}}: {{W+|lv|ekonomika|m}}, {{W+|lv|saimniecība|m}}
* {{Z|ms}}: {{W+|ms|ekonomi}}
* {{Z|mi}}: {{W-|mi|ōhanga}}, {{W-|mi|taiōhanga}}
* {{Z|hu}}: {{W+|hu|gazdaság}}
* {{Z|mn}}:
*: Kirîlî: {{W-|mn|аж ахуй}}
* {{Z|oc}}: {{W+|oc|economia|m}}
* {{Z|pl}}: {{W+|pl|gospodarka|m}}
* {{Z|pt}}: {{W+|pt|economia|m}}
* {{Z|ru}}: {{W+|ru|эконо́мия|m}}
* {{Z|scn}}: {{W-|scn|acunumìa|m}}, {{W-|scn|cunumìa|m}}, {{W+|scn|ecunumìa|m}}
* {{Z|es}}: {{W+|es|economía|m}}
* {{Z|sw}}: {{W+|sw|uchumi}}
* {{Z|sv}}: {{W+|sv|ekonomi|g}}, {{W+|sv|hushållning|g}}
* {{Z|tl}}: {{W+|tl|ekonomiya}}
* {{Z|tr}}: {{W+|tr|ekonomi}}, {{W+|tr|iktisat}}, {{W-|tr|denlik}}
* {{Z|ur}}: {{W-|ur|مَعِیشَت|m|tr=ma'išat}}
* {{Z|uk}}: {{W+|uk|еконо́мія|m}}
* {{Z|el}}: {{W+|el|οικονομία|m}}
{{werger-bin}}
:{{werger çavkanî|en|economy|beş=Ev qismê Wergerê|oldid=75875500}}
=== Rengdêr ===
{{ku-tewîn-rd|aborî}}
{{rengdêr|ku}}
# [[iqtisadî]], [[ekonomîk]], [[ekonomîkî]], [[têkildarî]] [[aborî#Navdêr|aboriyê]]:
#: ''pirsên aborî, mijarên aborî, biryarên aborî''
# [[erzan|Erzan]], ne [[giran]], ne [[bihadar]].
#: ''Min bilêtek '''aborî''' ya trênê kirrî.''
==== Werger ====
{{werger-ser|iqtisadî, têkildarî aboriyê}}
* {{Z|sq}}: {{W+|sq|ekonomik}}
* {{Z|de}}: {{W+|de|ökonomisch}}, {{W+|de|Wirtschaft|cuda=Wirtschafts-}}
* {{Z|az}}: {{W-|az|iqtisadi}}
* {{Z|be}}: {{W-|be|эканамі́чны}}, {{W-|be|гаспада́рскi}}
* {{Z|bn}}: {{W-|bn|আর্থিক}}
* {{Z|br}}: {{W+|br|armerzhel}}
* {{Z|bg}}: {{W+|bg|икономи́чески}}, {{W-|bg|стопа́нски}}
* {{Z|my}}: {{W+|my|စီးပွားရေး}}
* {{Z|cs}}: {{W+|cs|hospodářský}}
* {{Z|zh}}:
*: {{Z|cmn}}: {{W+|cmn|經濟|tr=jīngjì}}
* {{Z|da}}: {{W-|da|økonomisk}}
* {{Z|ar}}: {{W-|ar|اِقْتِصَادِيّ}}
* {{Z|hy}}: {{W+|hy|տնտեսական}}
* {{Z|eo}}: {{W-|eo|ekonomia}}
* {{Z|et}}: {{W-|et|majanduslik}}
* {{Z|fa}}: {{W+|fa|اقتصادی|tr=eqtesâdi}}
* {{Z|fi}}: {{W+|fi|kansantaloudellinen}}
* {{Z|fr}}: {{W+|fr|économique}}
* {{Z|gd}}: {{W-|gd|eagonomach}}
* {{Z|gl}}: {{W+|gl|económico}}
* {{Z|ka}}: {{W-|ka|ეკონომიკური}}
* {{Z|hi}}: {{W+|hi|आर्थिक}}
* {{Z|nl}}: {{W+|nl|economisch}}
* {{Z|he}}: {{W-|he|כַּלְכָּלִי|tr=kalkalí}}
* {{Z|en}}: {{W+|en|economic}}
* {{Z|ga}}: {{W-|ga|eacnamaíoch}}, {{W-|ga|eacnamúil}}
* {{Z|it}}: {{W+|it|economico}}
* {{Z|is}}: {{W-|is|hagfræðilegur}}
* {{Z|ja}}: {{W+|ja|経済|tr=けいざいの, keizai no|cuda=経済の}}, {{W+|ja|経済的|tr=けいざいてきな, keizaiteki na|cuda=経済的な}}
* {{Z|ca}}: {{W+|ca|econòmic}}
* {{Z|ky}}: {{W+|ky|экономикалык}}
* {{Z|ko}}: {{W+|ko|경제|cuda=경제-의}}
* {{Z|lad}}: {{W-|lad|ekonomiko}}
* {{Z|lv}}: {{W-|lv|ekonomisks}}
* {{Z|lo}}: {{W+|lo|ເສດຖະກິດ}}
* {{Z|lt}}: {{W+|lt|ekonominis}}
* {{Z|mk}}: {{W-|mk|економски}}
* {{Z|ms}}: {{W+|ms|ekonomi}}
* {{Z|mt}}: {{W-|mt|ekonomiku}}
* {{Z|hu}}: {{W+|hu|gazdasági}}
* {{Z|mn}}:
*: Kirîlî: {{W-|mn|аж ахуй|cuda=аж ахуйн}}
* {{Z|no}}:
*: {{Z|nb}}: {{W+|nb|økonomisk}}
* {{Z|oc}}: {{W+|oc|economic}}
* {{Z|ug}}: {{W-|ug|ئىقتىسادىي}}
* {{Z|uz}}: {{W+|uz|iqtisodiy}}
* {{Z|ps}}: {{W-|ps|وټه ييز|tr=wëṭa yiz}}, {{W+|ps|اقتصادي|tr=eqtesādi}}
* {{Z|pl}}: {{W+|pl|ekonomiczny}}, {{W+|pl|gospodarczy}}
* {{Z|pt}}: {{W+|pt|económico}}, {{W+|pt|econômico}}
* {{Z|kk}}: {{W-|kk|экономикалық}}
* {{Z|ro}}: {{W+|ro|economic}}
* {{Z|ru}}: {{W+|ru|экономи́ческий}}, {{W+|ru|хозя́йственный}}
* {{Z|sh}}:
*: Kirîlî: {{W-|sh|еко̀номскӣ}}
*: Latînî: {{W+|sh|ekònomskī}}
* {{Z|sk}}: {{W+|sk|hospodársky}}
* {{Z|sl}}: {{W-|sl|ekonomski}}, {{W-|sl|gospodarski}}
* {{Z|es}}: {{W+|es|económico}}
* {{Z|sv}}: {{W+|sv|ekonomisk}}
* {{Z|tg}}: {{W-|tg|иқтисодӣ}}
* {{Z|tl}}: {{W-|tl|agimatin}}
* {{Z|th}}: {{W+|th|เศรษฐกิจ}}
* {{Z|tr}}: {{W+|tr|ekonomik}}, {{W+|tr|iktisadi}}
* {{Z|tr}}: {{W-|tr|مُعاشی|tr=mu'āśī}}, {{W-|ur|اِقْتِصادی|tr=iqtisādī}}
* {{Z|tk}}: {{W-|tk|ykdysady}}
* {{Z|uk}}: {{W+|uk|економі́чний}}, {{W-|uk|господа́рський}}
* {{Z|vi}}: {{W+|vi|kinh tế}}
* {{Z|km}}: {{W+|km|សេដ្ឋកិច្ច}}
* {{Z|yi}}: {{W-|yi|עקאָנאָמיש}}
* {{Z|el}}: {{W+|el|οικονομικός}}
{{werger-bin}}
:{{werger çavkanî|en|economic|beş=Ev qismê Wergerê|oldid=75961449}}
== {{ziman|zza}} ==
=== Navdêr ===
{{navdêr|ckb|sc=Latn}}
# aborî, [[ekonomî]], [[îqtîsad]]<ref>http://www.kovarabir.com/wp-content/uploads/Ferheng%C3%AA-Dimil%C3%AE-Zazak%C3%AE-%C3%BB-Kurmanc%C3%AE-A-a.pdf</ref>.
#* {{bêmînak|zza}}
=== Çavkanî ===
{{çavkanî}}
2lztxf295824gvdzhbwd6d32o8dwv8a
selef
0
19089
6241552
6098479
2026-07-10T13:37:08Z
Zerwanda
12183
/* Etîmolojî */
6241552
wikitext
text/x-wiki
== {{ziman|ku}} ==
=== Bilêvkirin ===
<!-- * {{ku-IPA}} -->
* {{ku-kîte}}
=== Navdêr ===
{{ku-tewîn-nav|selef|mê}}
{{navdêr|ku|z=m}}
# [[faîz]], [[riba]], [[pare]]yê [[zêde]] yê [[divê]] kesa/ê [[deyngir]] bide kesa/ê [[deynder]]<br> (bo nimûne, dema kesek 100 euro bi deyn bide kesekî û 120 euro dîsan lê bên vegerrandin, 20 euroyên zêde faîz e.)
#* {{bêmînak|ku}}
==== Herwiha ====
* {{g|ku|fayiz}}
* {{g|ku|fayîz}}
==== Jê ====
{{kol3|ku|cure=Jê
|selefxwarî<pos:rengdêr>
|bêselef
|bêselefî
|bêselefîtî
|bêseleftî
|biselef
|biselefî
|biselefîtî
|biseleftî
|selefdar
|selefdarî
|selefdarîtî
|selefdartî
|selefder
|selefderî
|selefderîtî
|selefdertî
|dêr
|selefdêr
|selefdêrî
|selefdêrîtî
|selefdêrtî
|selefgir
|selefgirî
|selefgirîtî
|selefî
|selefstîn
|selefstînî
|selefstînîtî
|selefwergir
|selefwergirî
|selefwergirîtî
}}
==== Etîmolojî ====
Ji {{ji|ar|ku|سلف|ts=sellefe|w=deyn dan}}.
==== Werger ====
{{werger-ser}}
* {{Z|de}}: {{W+|de|Vorfahr|m}}, {{W+|de|Zins|m}}, {{W+|de|vergangen}}, {{W+|de|Vorgänger|m|guman=erê}}
* {{Z|ar}}: {{W+|ar|ربا|guman=erê}}
* {{Z|fa}}: {{W+|fa|بدهی}}
* {{Z|fi}}: {{W+|fi|korko}} (lisämaksu)
* {{Z|fr}}: {{W+|fr|intérêt|m}}
* {{Z|nl}}: {{W+|nl|interest}}
* {{Z|en}}: {{W+|en|interest}}, (additional payment) {{W+|en|apple core|guman=erê}}
* {{Z|pt}}: {{W+|pt|juros|m}}
* {{Z|ro}}: {{W-|ro|dobanda}}
* {{Z|tr}}: {{W+|tr|faiz}}, {{W+|tr|getiri}}, {{W+|tr|grup}}, {{W+|tr|kafile}}, {{W-|tr|önceki yıl}}, {{W+|tr|selef}}, {{W+|tr|tefe|guman=erê}}, {{W+|tr|öncel|guman=erê}}
{{werger-bin}}
== {{ziman|tr}} ==
=== Rengdêr ===
{{rengdêr|tr}}
# [[pêşrew]], [[pêşawer]], [[selef]]
#* {{bêmînak|tr}}
iskze14vobkgmichrhme1jnj2hou52g
6241556
6241552
2026-07-10T14:56:04Z
Wikihez
7344
/* Navdêr */ [[Bikarhêner:Wikihez/templateScript2.js|TS]]: sererastkirin
6241556
wikitext
text/x-wiki
== {{ziman|ku}} ==
=== Bilêvkirin ===
<!-- * {{ku-IPA}} -->
* {{ku-kîte}}
=== Navdêr ===
{{ku-tewîn-nav|selef|mê}}
{{navdêr|ku|z=m}}
# [[pare|Pare]]yê [[zêde]] yê [[divê]] kesa/ê [[deyngir]] bide kesa/ê [[deynder]]<br> (bo nimûne, dema kesek 100 euro bi deyn bide kesekî û 120 euro dîsan lê bên vegerrandin, 20 euroyên zêde faîz e.)
#: {{hevmane|ku|faîz|riba}}
#* {{bêmînak|ku}}
==== Herwiha ====
* {{g|ku|fayiz}}
* {{g|ku|fayîz}}
==== Jê ====
{{kol3|ku|cure=Jê
|selefxwarî<pos:rengdêr>
|bêselef
|bêselefî
|bêselefîtî
|bêseleftî
|biselef
|biselefî
|biselefîtî
|biseleftî
|selefdar
|selefdarî
|selefdarîtî
|selefdartî
|selefder
|selefderî
|selefderîtî
|selefdertî
|dêr
|selefdêr
|selefdêrî
|selefdêrîtî
|selefdêrtî
|selefgir
|selefgirî
|selefgirîtî
|selefî
|selefstîn
|selefstînî
|selefstînîtî
|selefwergir
|selefwergirî
|selefwergirîtî
}}
==== Etîmolojî ====
Ji {{ji|ar|ku|سلف|ts=sellefe|w=deyn dan}}.
==== Werger ====
{{werger-ser}}
* {{Z|de}}: {{W+|de|Vorfahr|m}}, {{W+|de|Zins|m}}, {{W+|de|vergangen}}, {{W+|de|Vorgänger|m|guman=erê}}
* {{Z|ar}}: {{W+|ar|ربا|guman=erê}}
* {{Z|fa}}: {{W+|fa|بدهی}}
* {{Z|fi}}: {{W+|fi|korko}} (lisämaksu)
* {{Z|fr}}: {{W+|fr|intérêt|m}}
* {{Z|nl}}: {{W+|nl|interest}}
* {{Z|en}}: {{W+|en|interest}}, (additional payment) {{W+|en|apple core|guman=erê}}
* {{Z|pt}}: {{W+|pt|juros|m}}
* {{Z|ro}}: {{W-|ro|dobanda}}
* {{Z|tr}}: {{W+|tr|faiz}}, {{W+|tr|getiri}}, {{W+|tr|grup}}, {{W+|tr|kafile}}, {{W-|tr|önceki yıl}}, {{W+|tr|selef}}, {{W+|tr|tefe|guman=erê}}, {{W+|tr|öncel|guman=erê}}
{{werger-bin}}
== {{ziman|tr}} ==
=== Rengdêr ===
{{rengdêr|tr}}
# [[pêşrew]], [[pêşawer]], [[selef]]
#* {{bêmînak|tr}}
91kf0yc6p3jci8ptkrt5esvka13ej89
Artikel
0
115907
6241579
6065047
2026-07-10T20:22:10Z
Wikihez
7344
/* */ bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re
6241579
wikitext
text/x-wiki
{{bnr-h|artîkel}}
== {{ziman|de}} ==
=== Bilêvkirin ===
* {{IPA|de|[aʁˈtiːkl̩]}}
* {{deng|de|De-Artikel2.ogg|Deng|dever=Berlîn, Almanya}}
* {{deng|de|LL-Q188 (deu)-Sebastian Wallroth-Artikel.wav|Deng|dever=Berlîn, Almanya}}
* {{deng|de|De-Artikel.ogg|Deng}}
* {{kîte|de|Ar|ti|kel}}
=== Navdêr ===
{{navdêr|de|z=n}}
# [[gotar]], [[nivîsar]]
ay9s2u944mah7f7qk3nxrzu4tx1s6uu
Bikarhêner:Wikihez/test.js
2
969083
6241544
6241543
2026-07-10T13:10:58Z
Wikihez
7344
6241544
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 input[type='text']," +
"#wiktvi-start-form textarea {" +
" resize: both;" +
" overflow: auto;" +
" box-sizing: border-box;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî binivîse. Ji bo tercimeyan beşa Wergerê bi kar bîne.",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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 = $(mw.html.element("input", {
type: "text",
"class": currentInput.attr("class") }));
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
stepDiv.append(input);
}
// Custom
else if (typeof(step.build) === "function") {
input = step.build(stepDiv);
}
// Text field(s)
else {
input = $(mw.html.element("input", {
type: "text",
"class": "wiktvi-start-step-field",
id: "wiktvi-start-" + step.id + "-field" }));
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
do8vg0nclqlm37uupbkju730ljf8pf0
6241545
6241544
2026-07-10T13:15:37Z
Wikihez
7344
6241545
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 input[type='text']," +
"#wiktvi-start-form textarea {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî binivîse. Ji bo tercimeyan beşa Wergerê bi kar bîne.",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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 = $(mw.html.element("input", {
type: "text",
"class": currentInput.attr("class") }));
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
stepDiv.append(input);
}
// Custom
else if (typeof(step.build) === "function") {
input = step.build(stepDiv);
}
// Text field(s)
else {
input = $(mw.html.element("input", {
type: "text",
"class": "wiktvi-start-step-field",
id: "wiktvi-start-" + step.id + "-field" }));
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
eywplvrhj1ez155ibz4fo74086ft7cc
6241546
6241545
2026-07-10T13:20:35Z
Wikihez
7344
6241546
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box;" +
" vertical-align: top;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî binivîse. Ji bo tercimeyan beşa Wergerê bi kar bîne.",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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", "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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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", "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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
kjwx176uku700ti1kqrof4xwzc3x70b
6241547
6241546
2026-07-10T13:24:23Z
Wikihez
7344
6241547
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box;" +
" vertical-align: top;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî 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": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
18cu6mhchig8czcynsc5v31ihoi6ugn
6241548
6241547
2026-07-10T13:27:16Z
Wikihez
7344
6241548
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" height: 1.8em !important;" +
" min-height: 1.8em !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî 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": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
trsvmdr4fw1tkfmqh758iniqythrxp2
6241549
6241548
2026-07-10T13:28:43Z
Wikihez
7344
([[m:Special:MyLanguage/User:Jon Harald Søby/diffedit|diffedit]])
6241549
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" height: 0.5em !important;" +
" min-height: 0.5em !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî 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": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
ozogzigv0vrcg3lf3cb00tqjteoxtx2
6241550
6241549
2026-07-10T13:30:02Z
Wikihez
7344
6241550
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box !important;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" height: calc(1em + 8px) !important;" +
" min-height: calc(1em + 8px) !important;" +
" padding-top: 2px !important;" +
" padding-bottom: 2px !important;" +
" line-height: 1.4 !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî 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": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
f8jchelkcj7r68zvs3is1frd55wul4b
6241551
6241550
2026-07-10T13:32:03Z
Wikihez
7344
6241551
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box !important;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" width: 20em !important;" +
" height: calc(1em + 8px) !important;" +
" min-height: calc(1em + 8px) !important;" +
" padding-top: 2px !important;" +
" padding-bottom: 2px !important;" +
" line-height: 1.4 !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Maneya peyvê di nivîsa sade de bi kurmancî 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": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Serê neêşe ne hewceyî destmalê ye."
};
var pos = values.pos;
return values.lang === "ku" ? examples[pos] : transExamples[pos];
},
getOutput: function (values, callback) {
var text = $.map(values.dfn, function (dfn, i) {
dfn = $.trim(dfn);
if (!dfn) return undefined;
// Capitalize the first word.
if (dfn[0] !== dfn[0].toUpperCase()) {
dfn = capitalize(dfn);
}
// Punctuate the definition.
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
// Generate the output for dfn
var output = "# " + dfn;
// Get the corresponding nimunes for the current dfn
var nimunes = i === 0 && values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
output += formatNimune(nimunes, values.lang);
return output;
}).join("\n") + "\n\n";
// Check if dfn is not empty before calling $.wiktviLinkify
if ($.trim(values.dfn.join("")) !== "") {
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
} else {
// Get the corresponding nimunes for the current dfn
var nimunes = values.nimune ? values.nimune : [];
// Trim each nimune
nimunes = nimunes.map(function(nimune) {
return $.trim(nimune);
});
// Use the default value if dfn is empty
text = "# {{mane?|" + values.lang + "}}" + formatNimune(nimunes, values.lang) + "\n\n";
callback(text);
}
} },
nimune: {
id: "nimune",
name: "nimûne",
question_fmt: "Nimûneyên bikaranîna peyvê binivîse (hemû ji bo maneya yekê)",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
} },
variant: makeWordListStep("variant", "herwiha", "Guhartoyên peyvê binivîse", "Herwiha", "g"),
syn: makeWordListStep("syn", "hevmane", undefined, "Hevmane", "g"),
ant: makeWordListStep("ant", "dijmane", undefined, "Dijmane", "g"),
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.nimune, steps.variant, steps.syn, steps.ant, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
entry += steps.pos.output(values);
steps.dfn.getOutput(values, function (output) {
entry += output;
entry += steps.variant.output(values);
entry += steps.syn.output(values);
entry += steps.ant.output(values);
entry += steps.je.output(values);
entry += steps.tekildar.output(values);
entry += steps.etym.output(values);
entry += steps.trans.output(values);
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + values.dfn.join("; ");
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
ldeyyp1mbjr7p9e5lnrsbbmx54icxza
6241553
6241551
2026-07-10T13:42:53Z
Wikihez
7344
6241553
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box !important;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" width: 20em !important;" +
" height: calc(1em + 8px) !important;" +
" min-height: calc(1em + 8px) !important;" +
" padding-top: 2px !important;" +
" padding-bottom: 2px !important;" +
" line-height: 1.4 !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
build: function (stepDiv) {
var list = $("<ol class='wiktvi-dfn-list'></ol>");
list.append(steps.dfn.buildSenseBlock(stepDiv));
stepDiv.append(list);
// Return null — prepareInput is a no-op for custom steps
// that manage their own change events.
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
qntlwskg6lgbic3iwytnhc0aepsy1t2
6241554
6241553
2026-07-10T13:52:03Z
Wikihez
7344
6241554
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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 {" +
" resize: both !important;" +
" overflow: auto !important;" +
" box-sizing: border-box !important;" +
" vertical-align: top;" +
"}" +
"#wiktvi-start-form textarea.wiktvi-start-narrow {" +
" width: 20em !important;" +
" height: calc(1em + 8px) !important;" +
" min-height: calc(1em + 8px) !important;" +
" padding-top: 2px !important;" +
" padding-bottom: 2px !important;" +
" line-height: 1.4 !important;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
tkuqt1ps2chmibktffrq4tzvl5o8qyp
6241555
6241554
2026-07-10T14:23:25Z
Wikihez
7344
6241555
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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",
multiple: true,
narrow: true,
rows: 2,
keyName: "ziman",
visible: function (values) {
return values.lang === "ku" && values.pos;
},
disabledKeys: {
"navz": true,
"ku": true },
example: function (values) {
var examples = 'Di navbera peyvan de bêhnok "," bi kar bîne.';
return examples;
},
output: function (values) {
var rows = [];
$.each(values.trans, function (lang, words) {
if (words) rows.push([lang, words]);
});
var outputString;
if (values.lang === "ku") {
outputString = "\n\n==== Werger ====\n{{werger-ser}}";
// Check if there are translations
if (rows.length) {
outputString += "\n";
// Sort the rows
rows.sort(function (a, b) {
var aLang = langsByCode[a[0]] || [];
var bLang = langsByCode[b[0]] || [];
return (aLang[2] || "").localeCompare(bLang[2] || "", "ku");
});
// Add the translations
outputString += $.map(rows, function (row, i) {
var words = escapeTemplateParam(row[1]).replace(/(\s*[,;()]+\s*)/g, "}}$1{{W|" + row[0] + "|");
return "* {{Z|" + row[0] + "}}: {{W|" + row[0] + "|" + words + "}}";
}).join("\n");
}
// Add the closing section header
outputString += "\n{{werger-bin}}\n\n";
}else {
outputString = "";
}
return outputString;
} },
};
steps.trans.keys = steps.lang.choices;
var ordered_steps = [
steps.lang, steps.pron, steps.pos, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
s1qtfxc59i2ivj0ko8wb3josrzz78kd
6241557
6241555
2026-07-10T17:18:04Z
Wikihez
7344
6241557
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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 (reuse chosen options).
var langSel = $(mw.html.element("select", {
"class": "wiktvi-start-step-keyfield wiktvi-start-narrow" }));
langSel.attr("data-placeholder", "Ziman hilbijêre");
populateMenus(langSel, steps.trans.keys || [], steps.trans.disabledKeys);
langSel.chosen(chosenOptions);
// 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));
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", "Werger…");
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) {
list.append(steps.trans.buildRow(stepDiv));
// Update chosen on the new row's select after it's in DOM.
list.children("li.wiktvi-trans-row:last-child")
.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);
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
dsi2txiha3y4c1ggut211qcp0w246c0
6241558
6241557
2026-07-10T17:21:08Z
Wikihez
7344
6241558
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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?",
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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));
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", "Werger…");
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.
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 now that the select is in the DOM.
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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)));
}
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
niakeryw156tzgsh0ft7cxjni73mwxb
6241559
6241558
2026-07-10T17:28:05Z
Wikihez
7344
6241559
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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");
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 };
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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));
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", "Werger…");
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.
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 now that the select is in the DOM.
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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);
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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);
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
cfchrq1zkrvv6a2nz1r7zthxb6deazw
6241560
6241559
2026-07-10T17:33:24Z
Wikihez
7344
6241560
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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; }" +
".wiktvi-native-select-wrap input[type='search'] {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" margin-bottom: 4px;" +
" box-sizing: border-box;" +
"}" +
".wiktvi-native-select-wrap select {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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, chosen is replaced with a native <select> preceded by a
* live-filter <input>. The filter hides non-matching <option> elements
* by rebuilding the option list on each keystroke.
*
* The returned object mimics the jQuery chosen API surface used elsewhere:
* .chosen(opts) — no-op (already initialised)
* .trigger("chosen:updated") — repopulates the native select
* .val() — native select .val()
* .on("change", fn) — native select change event
*/
function wrapNativeSelect(select) {
// Build a small filter input above the select.
var wrapper = $("<span class='wiktvi-native-select-wrap'></span>");
var filterInput = $("<input type='search'>")
.attr("placeholder", select.attr("data-placeholder") || "Lêbigere…")
.addClass("wiktvi-start-narrow");
// Store the full option list so we can re-filter without losing entries.
var allOptions = [];
function cacheOptions() {
allOptions = [];
select.find("option").each(function () {
allOptions.push({
value: $(this).val(),
text: $(this).text(),
disabled: $(this).prop("disabled")
});
});
}
cacheOptions();
function applyFilter(query) {
var q = query.trim().toLowerCase();
var currentVal = select.val();
select.empty();
$.each(allOptions, function (_, opt) {
if (!q || opt.text.toLowerCase().indexOf(q) !== -1) {
var el = $("<option></option>").val(opt.value).text(opt.text);
if (opt.disabled) el.prop("disabled", true);
select.append(el);
}
});
// Restore selection if it's still visible.
if (currentVal) select.val(currentVal);
}
filterInput.on("input", function () {
applyFilter($(this).val());
});
// chosen:updated → re-cache options (called after ziman.json loads).
select.on("chosen:updated", function () {
cacheOptions();
applyFilter(filterInput.val());
});
// Expose a no-op .chosen() so call sites don't need guarding.
select.chosen = function () { return select; };
wrapper.append(filterInput).append($("<br>")).append(select);
return wrapper;
}
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
qiktni171nx5m0bjevxtzckdypm6v42
6241561
6241560
2026-07-10T17:40:01Z
Wikihez
7344
6241561
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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; }" +
".wiktvi-native-select-wrap input[type='search'] {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" margin-bottom: 4px;" +
" box-sizing: border-box;" +
"}" +
".wiktvi-native-select-wrap select {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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, chosen is replaced with a native <select> preceded by a
* live-filter <input>. The filter hides non-matching <option> elements
* by rebuilding the option list on each keystroke.
*
* The returned object mimics the jQuery chosen API surface used elsewhere:
* .chosen(opts) — no-op (already initialised)
* .trigger("chosen:updated") — repopulates the native select
* .val() — native select .val()
* .on("change", fn) — native select change event
*/
function wrapNativeSelect(select) {
// Build a small filter input above the select.
var wrapper = $("<span class='wiktvi-native-select-wrap'></span>");
var filterInput = $("<input type='search'>")
.attr("placeholder", select.attr("data-placeholder") || "Lêbigere…")
.addClass("wiktvi-start-narrow");
// Store the full option list so we can re-filter without losing entries.
var allOptions = [];
function cacheOptions() {
allOptions = [];
select.find("option").each(function () {
allOptions.push({
value: $(this).val(),
text: $(this).text(),
disabled: $(this).prop("disabled")
});
});
}
cacheOptions();
function applyFilter(query) {
var q = query.trim().toLowerCase();
var currentVal = select.val();
select.empty();
$.each(allOptions, function (_, opt) {
if (!q || opt.text.toLowerCase().indexOf(q) !== -1) {
var el = $("<option></option>").val(opt.value).text(opt.text);
if (opt.disabled) el.prop("disabled", true);
select.append(el);
}
});
// Restore selection if it's still visible.
if (currentVal) select.val(currentVal);
// If filtering left exactly one selectable option, auto-select it
// and fire change so downstream steps (refresh) react immediately.
var selectableOpts = select.find("option:not([disabled])").filter(function () {
return $(this).val() !== "";
});
if (selectableOpts.length === 1) {
var autoVal = selectableOpts.first().val();
if (autoVal !== currentVal) {
select.val(autoVal);
select.trigger("change");
}
}
}
filterInput.on("input", function () {
applyFilter($(this).val());
});
// chosen:updated → re-cache options (called after ziman.json loads).
select.on("chosen:updated", function () {
cacheOptions();
applyFilter(filterInput.val());
});
// Expose a no-op .chosen() so call sites don't need guarding.
select.chosen = function () { return select; };
wrapper.append(filterInput).append($("<br>")).append(select);
return wrapper;
}
var langsByCode = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
3as63zmcyut442hrov3w8txwtz9s78n
6241562
6241561
2026-07-10T17:43:50Z
Wikihez
7344
6241562
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
choices: [
["navdêr", "Navdêr"],
["navdêr/m", "Navdêra mê"],
["navdêr/n", "Navdêra nêr"],
["navdêr/mn", "Navdêra mê û nêr"],
["navdêr/nt", "Navdêra nêtar"],
["lêker", "Lêker"],
["lêker/gh", "Lêkera gerguhêz"],
["lêker/ngh", "Lêkera negerguhêz"],
["lêker/x", "Lêkera xwerû"],
["lêker/x-gh", "Lêkera xwerû û gerguhêz"],
["lêker/x-ngh", "Lêkera xwerû û nergerguhêz"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/p-gh", "Lêkera pêkhatî û gerguhêz"],
["lêker/p-ngh", "Lêkera pêkhatî û negerguhêz"],
["lêker/b", "Lêkera biwêjî"],
["lêker/b-gh", "Lêkera biwêjî û gerguhêz"],
["lêker/b-ngh", "Lêkera biwêjî û negerguhêz"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["serenav/m", "Serenava mê"],
["serenav/n", "Serenava nêr"],
["serenav/mn", "Serenava mê û nêr"],
["serenav/nt", "Serenava nêtar"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan", "Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
// Split values.pos based on hyphen
var posParts = values.pos.split("/");
// Extract the part without gender
var posWithoutGender = posParts[0];
// Extract the gender part
var gender = posParts.length > 1 ? posParts[1] : "";
// Capitalize the first letter of the extracted part
var capitalizedPos = capitalize(posWithoutGender);
var outputString = "=== " + capitalizedPos + " ===\n";
const genders = {
'm': 'mê',
'n': 'nêr',
'mn': 'mê û nêr',
};
// Check the conditions for adding "{{ku-tewîn-nav}}"
if (!pageName.includes(" ") && gender && genders[gender] && (posWithoutGender === "navdêr" || posWithoutGender === "serenav") && values.lang === "ku") {
const genderName = genders[gender];
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderName + "}}\n";
}
outputString += "{{" + posWithoutGender + "|" + values.lang;
// Not: "nt" (nêtar) êdî nayê veguherandin bo "mn" li vir.
// Ne di tabloya "genders" de ("nt" hîna jî tabloya kişandinê
// nagire), ne jî li vir — "nt" ceribandî wek "nt" derdikeve
// di |z=-ê de, li şûna ku bibe "mê û nêr".
if (gender) {
if (posWithoutGender === "navdêr" || posWithoutGender === "serenav") {
outputString += "|z=" + gender;
}else if (posWithoutGender === "lêker") {
outputString += "|c=" + gender;
}
}
// Check the conditions for adding "|z=?"
if ((values.pos === "navdêr" || values.pos === "serenav") && values.lang === "ku") {
outputString += "|z=?";
}
// Add values from values.tr to the output string
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
// Complete the output string
outputString += "}}\n";
return outputString;
}
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
startForm.append(footer);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
6e3bmg5yumbeptk08z6m576wdotf7av
6241563
6241562
2026-07-10T18:06:57Z
Wikihez
7344
6241563
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
startForm.after(previewPanel);
$("#editform").hide().before(startForm);
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", "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"],
build);
});
//</nowiki>
t4wzzsj6w4drytt3tjto3kpb6p1ng4q
6241564
6241563
2026-07-10T18:10:55Z
Wikihez
7344
6241564
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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"],
build);
});
//</nowiki>
m6uoa481aljiujr9bhjt796qvm1hgvg
6241565
6241564
2026-07-10T18:32:04Z
Wikihez
7344
6241565
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
// Hardcoded fallback list for tr= step — overridden by LangMetadata if loaded.
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
// LangMetadata instance — populated asynchronously after the data script loads.
// Use langMeta.getGenders(code) and langMeta.guessScript(code) once available.
var langMeta = null;
// Maps TranslationAdder-Data gender codes → Kurmancî display labels for zayend.
// Extend this dict to support more gender values shown in the data script.
var genderLabels = {
"m": "Mê",
"n": "Nêr",
"mn": "Mê û nêr",
"nt": "Nêtar",
"m-p": "Mê (pirjimar)",
"n-p": "Nêr (pirjimar)",
"nt-p": "Nêtar (pirjimar)",
"g": "Giştî",
"g-p": "Giştî (pirjimar)",
"y": "Yekjimar",
"p": "Pirjimar"
};
// Latin-based script codes — languages using these do NOT need tr= transcription.
var latinScripts = { Latn: 1, Hebr: 1 };
// Returns true when a language needs manual transcription input.
function needsTr(langCode) {
if (langMeta) {
var sc = langMeta.guessScript(langCode);
// If script is unknown or Latin/Hebrew, no tr= needed.
if (!sc) return false;
return !latinScripts[sc];
}
// Fallback before LangMetadata loads.
return trRequired.indexOf(langCode) !== -1;
}
// Returns the zayend choices for the currently selected language.
// Uses LangMetadata if loaded, falls back to the static list.
function getZayendChoices(langCode) {
if (langMeta) {
var gs = langMeta.getGenders(langCode);
if (gs && gs.length) {
// Filter to single-word (non-plural) gender codes only — plural
// genders are not relevant to the zayend step.
return gs
.filter(function (g) { return genderLabels[g]; })
.map(function (g) { return [g, genderLabels[g]]; });
}
return []; // language has no genders
}
// Fallback: static list used before LangMetadata loads.
return [["m","Mê"],["n","Nêr"],["mn","Mê û nêr"],["nt","Nêtar"]];
}
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
if (!(values.lang && (values.pos === "navdêr" || values.pos === "serenav"))) return false;
// Hide if LangMetadata says this language has no genders.
return getZayendChoices(values.lang).length > 0;
},
// choices is populated dynamically via build() using getZayendChoices().
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
build: function (stepDiv, values) {
if (!values || !values.lang) return null;
var choices = getZayendChoices(values.lang);
var sel = stepDiv.find("#wiktvi-start-zayend-field");
if (!sel.length) {
// First build — create the select.
sel = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: "wiktvi-start-zayend-field" }));
sel.attr("data-placeholder", "Zayend hilbijêre");
if (isMobile) {
stepDiv.append(wrapNativeSelect(sel));
} else {
stepDiv.append(sel);
}
}
// Repopulate options every time (lang may have changed).
populateMenus(sel, choices);
if (!isMobile) sel.trigger("chosen:updated");
return isMobile ? null : sel;
},
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && needsTr(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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");
});
}
// Load TranslationAdder-Data.js for dynamic gender and script metadata.
// Works whether the script is loaded as a personal script or a gadget.
// Once loaded, LangMetadata becomes available on window; instantiate it
// and trigger a refresh so zayend/tr steps update immediately.
function loadLangMetadata() {
if (window.LangMetadata) {
langMeta = new window.LangMetadata();
refresh();
return;
}
// Try gadget first; fall back to user script URL.
var gadgetModule = "ext.gadget.TranslationAdder-Data";
var userScriptUrl = "https://ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript";
mw.loader.using(gadgetModule).then(function () {
if (window.LangMetadata) {
langMeta = new window.LangMetadata();
refresh();
}
}, function () {
// Gadget not found — load from user script URL.
mw.loader.load(userScriptUrl);
mw.loader.using("mediawiki.api").then(function () {
// Poll briefly until LangMetadata appears (script is async).
var tries = 0;
var poll = setInterval(function () {
if (window.LangMetadata || ++tries > 20) {
clearInterval(poll);
if (window.LangMetadata) {
langMeta = new window.LangMetadata();
refresh();
}
}
}, 200);
});
});
}
mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"],
function () { build(); loadLangMetadata(); });
});
//</nowiki>
38pg0ldk2t1052bln0eabckvdka69o4
6241566
6241565
2026-07-10T18:34:13Z
Wikihez
7344
6241566
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
// Hardcoded fallback list for tr= step — overridden by LangMetadata if loaded.
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
// LangMetadata instance — populated asynchronously after the data script loads.
// Use langMeta.getGenders(code) and langMeta.guessScript(code) once available.
var langMeta = null;
// Maps TranslationAdder-Data gender codes → Kurmancî display labels for zayend.
// Extend this dict to support more gender values shown in the data script.
var genderLabels = {
"m": "Mê",
"n": "Nêr",
"mn": "Mê û nêr",
"nt": "Nêtar",
"m-p": "Mê (pirjimar)",
"n-p": "Nêr (pirjimar)",
"nt-p": "Nêtar (pirjimar)",
"g": "Giştî",
"g-p": "Giştî (pirjimar)",
"y": "Yekjimar",
"p": "Pirjimar"
};
// Latin-based script codes — languages using these do NOT need tr= transcription.
var latinScripts = { Latn: 1, Hebr: 1 };
// Returns true when a language needs manual transcription input.
function needsTr(langCode) {
if (langMeta) {
var sc = langMeta.guessScript(langCode);
// If script is unknown or Latin/Hebrew, no tr= needed.
if (!sc) return false;
return !latinScripts[sc];
}
// Fallback before LangMetadata loads.
return trRequired.indexOf(langCode) !== -1;
}
// Returns the zayend choices for the currently selected language.
// Uses LangMetadata if loaded, falls back to the static list.
function getZayendChoices(langCode) {
if (langMeta) {
var gs = langMeta.getGenders(langCode);
if (gs && gs.length) {
// Filter to single-word (non-plural) gender codes only — plural
// genders are not relevant to the zayend step.
return gs
.filter(function (g) { return genderLabels[g]; })
.map(function (g) { return [g, genderLabels[g]]; });
}
return []; // language has no genders
}
// Fallback: static list used before LangMetadata loads.
return [["m","Mê"],["n","Nêr"],["mn","Mê û nêr"],["nt","Nêtar"]];
}
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
if (!(values.lang && (values.pos === "navdêr" || values.pos === "serenav"))) return false;
// Hide if LangMetadata says this language has no genders.
return getZayendChoices(values.lang).length > 0;
},
// choices is populated dynamically via build() using getZayendChoices().
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
build: function (stepDiv, values) {
if (!values || !values.lang) return null;
var choices = getZayendChoices(values.lang);
var sel = stepDiv.find("#wiktvi-start-zayend-field");
if (!sel.length) {
// First build — create the select.
sel = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: "wiktvi-start-zayend-field" }));
sel.attr("data-placeholder", "Zayend hilbijêre");
if (isMobile) {
stepDiv.append(wrapNativeSelect(sel));
} else {
stepDiv.append(sel);
}
}
// Repopulate options every time (lang may have changed).
populateMenus(sel, choices);
if (!isMobile) sel.trigger("chosen:updated");
return isMobile ? null : sel;
},
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && needsTr(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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");
});
}
// Load TranslationAdder-Data.js for dynamic gender and script metadata.
// Works whether the script is loaded as a personal script or a gadget.
// Once loaded, LangMetadata becomes available on window; instantiate it
// and trigger a refresh so zayend/tr steps update immediately.
function loadLangMetadata() {
if (window.LangMetadata) {
// Already available (e.g. loaded by another gadget earlier in the session).
try {
langMeta = new window.LangMetadata();
refresh();
} catch (e) {}
return;
}
var gadgetModule = "ext.gadget.TranslationAdder-Data";
var langUtilsModule = "ext.gadget.LanguageUtils";
var userScriptUrl = "https://ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript";
function tryInstantiate() {
if (!window.LangMetadata) return;
try {
langMeta = new window.LangMetadata();
refresh();
} catch (e) {}
}
// LanguageUtils must be loaded first — LangMetadata's constructor calls
// new ScriptUtils() which lives in that module.
mw.loader.using(langUtilsModule).then(function () {
// Now try loading the data script as a gadget.
mw.loader.using(gadgetModule).then(
function () { tryInstantiate(); },
function () {
// Gadget not registered — fall back to user script URL.
$.getScript(userScriptUrl).done(tryInstantiate);
}
);
}, function () {
// LanguageUtils gadget not found either — just try the data script
// directly and hope ScriptUtils is a no-op or already present.
$.getScript(userScriptUrl).done(tryInstantiate);
});
}
mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"],
function () { build(); loadLangMetadata(); });
});
//</nowiki>
1a66shckb5bfutd86vmn2isbfpag60f
6241567
6241566
2026-07-10T18:37:10Z
Wikihez
7344
6241567
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
// Hardcoded fallback list for tr= step — overridden by LangMetadata if loaded.
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
// LangMetadata instance — populated asynchronously after the data script loads.
// Use langMeta.getGenders(code) and langMeta.guessScript(code) once available.
var langMeta = null;
// Maps TranslationAdder-Data gender codes → Kurmancî display labels for zayend.
// Extend this dict to support more gender values shown in the data script.
var genderLabels = {
"m": "Mê",
"n": "Nêr",
"mn": "Mê û nêr",
"nt": "Nêtar",
"m-p": "Mê (pirjimar)",
"n-p": "Nêr (pirjimar)",
"nt-p": "Nêtar (pirjimar)",
"g": "Giştî",
"g-p": "Giştî (pirjimar)",
"y": "Yekjimar",
"p": "Pirjimar"
};
// Latin-based script codes — languages using these do NOT need tr= transcription.
var latinScripts = { Latn: 1, Hebr: 1 };
// Returns true when a language needs manual transcription input.
function needsTr(langCode) {
if (langMeta && typeof langMeta.getGenders === "function") {
var sc = langMeta.guessScript(langCode);
if (!sc) return false;
return !latinScripts[sc];
}
return trRequired.indexOf(langCode) !== -1;
}
// Returns the zayend choices for the currently selected language.
function getZayendChoices(langCode) {
if (langMeta && typeof langMeta.getGenders === "function") {
var gs = langMeta.getGenders(langCode);
if (gs && gs.length) {
return gs
.filter(function (g) { return genderLabels[g]; })
.map(function (g) { return [g, genderLabels[g]]; });
}
return [];
}
return [["m","Mê"],["n","Nêr"],["mn","Mê û nêr"],["nt","Nêtar"]];
}
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
if (!(values.lang && (values.pos === "navdêr" || values.pos === "serenav"))) return false;
// Hide if LangMetadata says this language has no genders.
return getZayendChoices(values.lang).length > 0;
},
// choices is populated dynamically via build() using getZayendChoices().
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
build: function (stepDiv, values) {
if (!values || !values.lang) return null;
var choices = getZayendChoices(values.lang);
var sel = stepDiv.find("#wiktvi-start-zayend-field");
if (!sel.length) {
// First build — create the select.
sel = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: "wiktvi-start-zayend-field" }));
sel.attr("data-placeholder", "Zayend hilbijêre");
if (isMobile) {
stepDiv.append(wrapNativeSelect(sel));
} else {
stepDiv.append(sel);
}
}
// Repopulate options every time (lang may have changed).
populateMenus(sel, choices);
if (!isMobile) sel.trigger("chosen:updated");
return isMobile ? null : sel;
},
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && needsTr(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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");
});
}
// Load TranslationAdder-Data.js for dynamic gender and script metadata.
// Works whether the script is loaded as a personal script or a gadget.
// Once loaded, LangMetadata becomes available on window; instantiate it
// and trigger a refresh so zayend/tr steps update immediately.
function loadLangMetadata() {
if (window.LangMetadata) {
try {
var inst = new window.LangMetadata();
if (typeof inst.getGenders === "function") {
langMeta = inst;
refresh();
}
} catch (e) {}
return;
}
var gadgetModule = "ext.gadget.TranslationAdder-Data";
var langUtilsModule = "ext.gadget.LanguageUtils";
var userScriptUrl = "https://ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript";
function tryInstantiate() {
if (!window.LangMetadata) return;
try {
var instance = new window.LangMetadata();
// Verify the instance is functional before assigning.
if (typeof instance.getGenders === "function") {
langMeta = instance;
refresh();
}
} catch (e) {}
}
// LanguageUtils must be loaded first — LangMetadata's constructor calls
// new ScriptUtils() which lives in that module.
mw.loader.using(langUtilsModule).then(function () {
// Now try loading the data script as a gadget.
mw.loader.using(gadgetModule).then(
function () { tryInstantiate(); },
function () {
// Gadget not registered — fall back to user script URL.
$.getScript(userScriptUrl).done(tryInstantiate);
}
);
}, function () {
// LanguageUtils gadget not found either — just try the data script
// directly and hope ScriptUtils is a no-op or already present.
$.getScript(userScriptUrl).done(tryInstantiate);
});
}
mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"],
function () { build(); loadLangMetadata(); });
});
//</nowiki>
2lewr37rnn4bpbldst644qrosyd5ntk
6241569
6241567
2026-07-10T18:40:48Z
Wikihez
7344
6241569
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
// Hardcoded fallback list for tr= step — overridden by LangMetadata if loaded.
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
// LangMetadata instance — populated asynchronously after the data script loads.
// Use langMeta.getGenders(code) and langMeta.guessScript(code) once available.
var langMeta = null;
// Maps TranslationAdder-Data gender codes → Kurmancî display labels for zayend.
// Extend this dict to support more gender values shown in the data script.
var genderLabels = {
"m": "Mê",
"n": "Nêr",
"mn": "Mê û nêr",
"nt": "Nêtar",
"m-p": "Mê (pirjimar)",
"n-p": "Nêr (pirjimar)",
"nt-p": "Nêtar (pirjimar)",
"g": "Giştî",
"g-p": "Giştî (pirjimar)",
"y": "Yekjimar",
"p": "Pirjimar"
};
// Latin-based script codes — languages using these do NOT need tr= transcription.
var latinScripts = { Latn: 1, Hebr: 1 };
// Returns true when a language needs manual transcription input.
function needsTr(langCode) {
if (langMeta && typeof langMeta.getGenders === "function") {
var sc = langMeta.guessScript(langCode);
if (!sc) return false;
return !latinScripts[sc];
}
return trRequired.indexOf(langCode) !== -1;
}
// Returns the zayend choices for the currently selected language.
function getZayendChoices(langCode) {
if (langMeta && typeof langMeta.getGenders === "function") {
var gs = langMeta.getGenders(langCode);
if (gs && gs.length) {
return gs
.filter(function (g) { return genderLabels[g]; })
.map(function (g) { return [g, genderLabels[g]]; });
}
return [];
}
return [["m","Mê"],["n","Nêr"],["mn","Mê û nêr"],["nt","Nêtar"]];
}
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
if (!(values.lang && (values.pos === "navdêr" || values.pos === "serenav"))) return false;
// Hide if LangMetadata says this language has no genders.
return getZayendChoices(values.lang).length > 0;
},
// choices is populated dynamically via build() using getZayendChoices().
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
build: function (stepDiv, values) {
if (!values || !values.lang) return null;
var choices = getZayendChoices(values.lang);
var sel = stepDiv.find("#wiktvi-start-zayend-field");
if (!sel.length) {
// First build — create the select.
sel = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: "wiktvi-start-zayend-field" }));
sel.attr("data-placeholder", "Zayend hilbijêre");
if (isMobile) {
stepDiv.append(wrapNativeSelect(sel));
} else {
stepDiv.append(sel);
}
}
// Repopulate options every time (lang may have changed).
populateMenus(sel, choices);
if (!isMobile) sel.trigger("chosen:updated");
return isMobile ? null : sel;
},
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && needsTr(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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");
});
}
// Load LanguageUtils.js then TranslationAdder-Data.js in sequence.
// LanguageUtils must come first because LangMetadata.guessScript calls
// new ScriptUtils() which is defined there. Neither is a gadget yet so
// both are fetched via $.getScript from the user-script URLs.
function loadLangMetadata() {
var langUtilsUrl = "https://ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/LanguageUtils.js&action=raw&ctype=text/javascript";
var transDataUrl = "https://ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript";
function tryInstantiate() {
if (!window.LangMetadata) return;
try {
var instance = new window.LangMetadata();
// getGenders has no external dependency — use it as a smoke test.
if (typeof instance.getGenders === "function") {
langMeta = instance;
refresh();
}
} catch (e) {}
}
// If both scripts are already loaded (e.g. by another gadget), instantiate now.
if (window.LangMetadata) {
tryInstantiate();
return;
}
$.getScript(langUtilsUrl).done(function () {
$.getScript(transDataUrl).done(tryInstantiate);
});
}
mw.loader.using(["jquery.chosen", "jquery.ui", "mediawiki.api"],
function () { build(); loadLangMetadata(); });
});
//</nowiki>
d5woc1hby8n2ehli1zs9z40ffakv7qp
6241570
6241569
2026-07-10T18:44:03Z
Wikihez
7344
Restored revision 6241564 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]])
6241570
javascript
text/javascript
// Çavkanî [[vi:MediaWiki:Gadget-start.js]]
//
// Guhertoya revîzekirî — 2026-07-10
// - Sereastkirin: hevoka kurte ya edîtê ("output" li şûna "values.dfn")
// - Sereastkirin: pageName nehatibû revandin berî lêkolîna RegExp-ê
// - Sereastkirin: "nt" (nêtar) êdî nayê veguherandin bo "mn" di |z=-ê de
// - Sereastkirin: mifteya nimûneya paremî "gotineke pêşiyan" e, ne "gp"
// (berê negihîştî bû ji ber vê şaşiyê)
// - Xurtkirin: têketina bikarhêner tê revandin berî ku bikeve şablonan
// (| û = dikarin sazkariya şablonê bişkênin)
// - Refaktorkirin: pênc gavên dubare (variant/syn/ant/je/tekildar) bûne
// yek fabrîkeya fonksiyonê; mantiqa "bêmînak" a dubarekirî bû yek fonksiyon
// - Rakirin: String.prototype.wiktviCapitalize (guherto: capitalize())
// - Rakirin: koda mirî (rowsNimune, output-ên tr/nimune yên qet nayên gazîkirin,
// şîroveya {{mẫu}} ya Wîetnamî ya ji orjînalê mabû)
// - Regexa navê zimên (header.name.match) hatiye hiştin wek xwe bi qesd
// - Xurtkirin: zimanan ji MediaWiki:Gadget-translation_editor.js/ziman.json
// tên barkirin; -pro û "zimanê destan" tên derxistin
// - Xurtkirin: zimanan bi koda zimanî jî tê lêgerandin (mînak "ku" → kurmancî)
// - Xurtkirin: hemû qutiyên nivîsê û textareayan dikarin mezin/biçûk bibin
// - Refaktorkirin: her mane êdî xweyê nimûne, herwiha, hevmane û dijmaneyên
// xwe yên taybet e; gavên serbixwe yên nimûne/herwiha/hevmane/dijmanê hatin
// rakirin û di bloka maneyê de yekgirtî bûn
//<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
}
// 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;" +
"}"
);
// Herfa ewil a peyvê 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 şîrovekirin) direvîne,
// daku nivîsa vekirî ya bikarhêner sazkariya ş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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* Rêzeke nimûneyan (ku berê hatine paqijkirin bi $.trim) vediguherîne
* beşa wikînivîsê ya di bin pênaseyekê de: an rêzikên "#: {{mk|...}}"
* bo her nimûneyekê, an "#* {{bêmînak|lang}}" ger tu nimûne tunebe.
* Vê mantiqê carekê tenê hebe — di kodê ya berê de du caran hatibû
* nivîsandin (bo dema pênase heye û dema pênase vala ye).
*/
function formatNimune(nimunes, lang) {
var hasNimune = nimunes && $.grep(nimunes, function (nimune) {
return nimune !== "";
}).length > 0;
if (!hasNimune) {
return "\n#* {{bêmînak|" + lang + "}}";
}
return $.map(nimunes, function (nimune) {
if (nimune === "") return undefined;
var bolded = nimune.replace(
new RegExp("(" + pageNameRe + "([^( |,|;|\\?|\\.|\\!)]+)?)", "ig"),
"'''$1'''");
return "\n#: {{mk|" + lang + "|" + escapeTemplateParam(bolded) + "}}";
}).join("");
}
/**
* Fabrîkeyek bo gavên "lîsteya peyvan" ên hevshibin: herwiha, hevmane,
* dijmane, jê, têkildar. 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["ku", "kurmancî"],
["de", "almanî"],
["ar", "erebî"],
["fa", "farisî"],
["fr", "fransî"],
["fi", "fînî"],
["en", "îngilîzî"],
["sv", "swêdî"],
["tr", "tirkî"] ],
output: function (values) {
return "== {{ziman|" + values.lang + "}} ==\n\n";
} },
pron: {
id: "pron",
name: "bilêvkirin",
question_fmt: "“{{PAGENAME}}” çawa tê bilêvkirin?",
visible: function (values) {
return false;
},
output: function (values) {
if (values.lang === "ku") {
return "=== Bilêvkirin ===\n* {{ku-IPA}}\n* {{ku-kîte}}\n\n";
}
return "";
} },
pos: {
id: "pos",
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî ya “{{PAGENAME}}” çi ye?",
visible: function (values) {
return values.lang;
},
question_br: true,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["lêker/p", "Lêkera pêkhatî"],
["lêker/b", "Lêkera biwêjî"],
["lêker/x", "Lêkera xwerû"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["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"] ],
output: function (values) {
var pos = values.pos || "";
var zayend = values.zayend || ""; // from the zayend 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).
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(" ") && zayend && genderNames[zayend] &&
(pos === "navdêr" || pos === "serenav") && values.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[zayend] + "}}\n";
}
outputString += "{{" + pos + "|" + values.lang;
if (pos === "navdêr" || pos === "serenav") {
if (zayend) {
outputString += "|z=" + zayend;
} else if (values.lang === "ku") {
// Unknown gender — prompt editor to fill it in.
outputString += "|z=?";
}
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (values.tr) {
outputString += "|tr=" + escapeTemplateParam(values.tr);
}
outputString += "}}\n";
return outputString;
}
},
/**
* Zayend (grammatical gender) — only shown for navdêr and serenav.
* Extend the choices dict here to add more genders in the future.
*/
zayend: {
id: "zayend",
name: "zayend",
question_fmt: "Zayenda peyvê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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"],
["ngh", "Negerguhêz"],
["x", "Gerguhêz û negerguhêz"] ],
output: function () { return ""; } // consumed by pos.output
},
tr: {
id: "tr",
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona peyvê",
multiple: false,
narrow: true,
visible: function (values) {
return values.lang && values.pos && trRequired.includes(values.lang);
} },
dfn: {
id: "dfn",
// required: true, ger mane tinebe [[Şablon:mane?]] bi kar bîne
name: "Mane",
question_fmt: "Mane û nimûneyên peyvê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (values) {
return values.lang && values.pos;
},
example: function (values) {
var examples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "Nimûne 'serê neêşe ne hewceyî destmalê ye'."
};
var transExamples = {
"navdêr": "Peyvên ji bo tiştan (sêv, heywan, qedeh) yan têgihan (dilşadî, bextiyarî hwd.) di rêzimanê de.",
"lêker": "Peyvên ji bo kirin an bûyînê wekî 'nivîsîn' yan 'xeber dan'.",
"rengdêr": "Peyvên yên ku çawaniya navdêran nîşan didin wekî 'sêva sor' yan 'xwarina şîrîn'.",
"hoker": "Peyvên ku dem, cih yan awayê kirinê diyar dikin wekî 'bi vî awayî' yan 'demkî'.",
"daçek": "Peyvên ku cih, dem yan tevgerê diyar dikin wekî 'di.. de' yan 'ji'.",
"cînav": "Peyvên ku li şûna navdêran tên bikaranîn daku navdêr neyên dubarekirin wekî 'ew' yan 'em'.",
"baneşan": "Peyvên ku hest, deng hwd. derdibirin wekî 'noşî!' yan 'aferîn'!",
"pêşgir": "ne-.",
"paşgir": "-van.",
"serenav": "Navdêrên ku kesayetiyên ferdî nîşan didin, wek navên kes, cih an rêxistinan nimûne 'London' yan 'Diyarbekir'.",
"gotineke pêşiyan": "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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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) 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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
nimune: readList("wiktvi-dfn-nimune"),
herwiha: readList("wiktvi-dfn-herwiha"),
hevmane: readList("wiktvi-dfn-hevmane"),
dijmane: readList("wiktvi-dfn-dijmane")
});
});
return senses;
},
getOutput: function (values, callback) {
var stepDiv = $("#wiktvi-start-dfn");
var senses = steps.dfn.getSenses(stepDiv);
var lang = values.lang;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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-rez", sense.herwiha);
out += wordLine("hevmane", sense.hevmane);
out += wordLine("dijmane", sense.dijmane);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
// No definitions entered — emit {{mane?}} with bêmînak.
text = "# {{mane?|" + lang + "}}\n#* {{bêmînak|" + lang + "}}\n\n";
callback(text);
return;
}
var didTryToLoad = function () {
$.wiktviLinkify(text, callback);
};
mw.loader.using("ext.gadget.linkify", didTryToLoad, didTryToLoad);
}
},
je: makeWordListStep("je", "jê", "Peyvên jê çêbûyî binivîse", "Jê", "g"),
tekildar: makeWordListStep("tekildar", "têkildar", "Peyvên têkildarî vê peyvê binivîse", "Têkildar", "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) {
return values.lang === "ku" && values.pos;
},
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", "Ziman 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", "Werger…");
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.zayend, steps.lektur, steps.tr,
steps.dfn, steps.je, steps.tekildar,
steps.etym, steps.trans];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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.trans.output(values);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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 gotareke nû bi kar bîne.");
var startForm = $("<form id='wiktvi-start-form'></form>");
var spinner;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
var previewCheck = $("<input type='checkbox' id='wiktvi-preview-toggle'>");
var previewLabel = $("<label for='wiktvi-preview-toggle'></label>")
.text(" Pêşdîtin");
var previewPanel = $("<pre id='wiktvi-preview-panel'></pre>").hide();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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", "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"],
build);
});
//</nowiki>
m6uoa481aljiujr9bhjt796qvm1hgvg
6241571
6241570
2026-07-10T19:27:05Z
Wikihez
7344
6241571
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through ext.gadget.headers.
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["î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"] ],
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).
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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 çawaniya 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 çawaniya 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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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", "binereherwiha", "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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
hx2lbojx907ea2zfxfg9n3uarpc8vtp
6241572
6241571
2026-07-10T19:28:46Z
Wikihez
7344
6241572
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["î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"] ],
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).
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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 çawaniya 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 çawaniya 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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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", "binereherwiha", "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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
ponzthqg4i1prol6jix8vxmyizl379h
6241573
6241572
2026-07-10T19:33:26Z
Wikihez
7344
6241573
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["î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"] ],
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).
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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 çawaniya 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 çawaniya 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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
k36sg4hz4vlash7202kutyha47wsieb
6241574
6241573
2026-07-10T19:42:16Z
Wikihez
7344
6241574
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["î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"] ],
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).
var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr", nt: "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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 çawaniya 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 çawaniya 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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
222nf4homrmstwkpyi22e1jo44ctxz5
6241575
6241574
2026-07-10T19:47:32Z
Wikihez
7344
6241575
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
choices: [
["navdêr", "Navdêr"],
["lêker", "Lêker"],
["rengdêr", "Rengdêr"],
["hoker", "Hoker"],
["serenav", "Serenav"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj"],
["cînav", "Cînav"],
["daçek", "Daçek"],
["girêdek", "Girêdek"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar"],
["hevok", "Hevok"],
["î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"] ],
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).
var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr", nt: "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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
cytvd2gopslk96srb5kxllqwj71oybt
6241576
6241575
2026-07-10T19:59:38Z
Wikihez
7344
6241576
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;" +
"}"
);
// 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 = {};
var trRequired = ["ckb", "sdh", "ar", "akk", "fa", "ja", "zh", "ru", "ko", "el", "hy", "ka"];
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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"],
["biwêj", "Biwêj (tabîr)"],
["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)"] ],
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).
var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr", nt: "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 and serenav.
* Extend the choices dict here to add more genders in the future.
*/
cinsiyet: {
id: "cinsiyet",
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (values) {
return values.lang && (values.pos === "navdêr" || values.pos === "serenav");
},
// Dictionary: value → display label. Add new genders here.
choices: [
["m", "Mê"],
["n", "Nêr"],
["mn", "Mê û nêr"],
["nt", "Nêtar"] ],
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 && trRequired.includes(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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
6wiihhtdnyynx9pbhdufpgn079ky5yl
6241577
6241576
2026-07-10T20:10:26Z
Wikihez
7344
6241577
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;" +
"}"
);
// 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 = {};
// `metadata` (nav bi kod, nirx bi {haswikt, sc, g, alt} hwd.) tê danîn li
// dawiya pelê — ev tenê valahiyeke pêşdibistanî ye daku skrîpt berî ku ew
// tabloya mezin were zêdekirin jî bêyî xeletî bimeşe.
var metadata = {};
/**
* Ma zimanê bi vî kodî ji bo transkrîpsiyonê (tr=) pêwîstiya wê heye?
* Berê rêzek zimanan bi destan hatibû danîn; niha ev ji tîpguhêziya
* (script) di metadata de tê wergirtin — ger tîpguhêziya sereke ya
* zimên ne latînî be, transkrîpsiyon pêwîst e.
*/
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: "Mê û nêr" };
/**
* 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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "Navdêr (îsm)"],
["lêker", "Lêker (fiîl)"],
["rengdêr", "Rengdêr (sifet)"],
["hoker", "Hoker (zerf)"],
["serenav", "Serenav (alem)"],
["artîkel", "Artîkel"],
["baneşan", "Baneşan (nîda)"],
["bazinedaçik", "Bazinedaçek"],
["biwêj", "Biwêj (tabîr)"],
["cînav", "Cînav (zemîr)"],
["daçek", "Daçek (herfa cer)"],
["girêdek", "Girêdek (herfa atif)"],
["gotineke pêşiyan","Gotineke pêşiyan (mesel)"],
["hejmar", "Hejmar (aded)"],
["hevok", "Hevok (cumle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav (îhtîsar)"],
["navgir", "Navgir"],
["paşdaçek", "Paşdaçek (edat)"],
["paşgir", "Paşgir"],
["pêşdaçek", "Pêşdaçek (herfa cer)"],
["pêşgir", "Pêşgir"],
["pirtik", "Pirtik (herf)"],
["reh", "Reh (cezr)"],
["sembol", "Sembol (remz)"],
["tîp", "Tîp (herf)"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
8g5kk535wh987fwrzsezcseigqv9fq6
6241578
6241577
2026-07-10T20:17:04Z
Wikihez
7344
6241578
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;" +
"}"
);
// 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 = {};
var 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","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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["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"],
["biwêj", "Biwêj (tabîr)"],
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
k4xh2om8fp4x6dsmwpz1i1cm2l236fa
6241580
6241578
2026-07-10T20:27:38Z
Wikihez
7344
6241580
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;" +
"}"
);
// 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 = {};
var 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","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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "Navdêr (îsm) — sêv, heywan, bextiyarî"],
["lêker", "Lêker (fiîl) — baz dan, xwarin, kirin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik, baş"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Bedirxan, Memo"],
["artîkel", "Artîkel — the, das, a"],
["baneşan", "Baneşan (nîda) — ox, ax, hey wax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu, em"],
["daçek", "Daçek (edat) — li, de, ji"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve, re"],
["paşgir", "Paşgir — -van, -ker, -lojî"],
["pêşdaçek", "Pêşdaçek — li, di, bi"],
["pêşgir", "Pêşgir — a-, ne-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
0gl9qxr3yv4njf9aa6x208aad8msroi
6241581
6241580
2026-07-10T20:29:39Z
Wikihez
7344
6241581
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;" +
"}"
);
// 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 = {};
var 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","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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "<code>Navdêr</code> (îsm) — sêv, heywan, bextiyarî"],
["lêker", "<code>Lêker</code> (fiîl) — baz dan, xwarin, kirin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik, baş"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Bedirxan, Memo"],
["artîkel", "Artîkel — the, das, a"],
["baneşan", "Baneşan (nîda) — ox, ax, hey wax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu, em"],
["daçek", "Daçek (edat) — li, de, ji"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve, re"],
["paşgir", "Paşgir — -van, -ker, -lojî"],
["pêşdaçek", "Pêşdaçek — li, di, bi"],
["pêşgir", "Pêşgir — a-, ne-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
srvhfax70qkc57fzkwq47lfc2tj6ysn
6241582
6241581
2026-07-10T20:30:12Z
Wikihez
7344
6241582
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;" +
"}"
);
// 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 = {};
var 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","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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "<b>Navdêr</b> (îsm) — sêv, heywan, bextiyarî"],
["lêker", "<code>Lêker</code> (fiîl) — baz dan, xwarin, kirin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik, baş"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Bedirxan, Memo"],
["artîkel", "Artîkel — the, das, a"],
["baneşan", "Baneşan (nîda) — ox, ax, hey wax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu, em"],
["daçek", "Daçek (edat) — li, de, ji"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve, re"],
["paşgir", "Paşgir — -van, -ker, -lojî"],
["pêşdaçek", "Pêşdaçek — li, di, bi"],
["pêşgir", "Pêşgir — a-, ne-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
mx396lisawv05l2ld3fhzitt5dohfnt
6241583
6241582
2026-07-10T20:33:10Z
Wikihez
7344
6241583
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "<b>Navdêr</b> (îsm) — sêv, heywan, bextiyarî"],
["lêker", "<code>Lêker</code> (fiîl) — baz dan, xwarin, kirin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik, baş"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Bedirxan, Memo"],
["artîkel", "Artîkel — the, das, a"],
["baneşan", "Baneşan (nîda) — ox, ax, hey wax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu, em"],
["daçek", "Daçek (edat) — li, de, ji"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve, re"],
["paşgir", "Paşgir — -van, -ker, -lojî"],
["pêşdaçek", "Pêşdaçek — li, di, bi"],
["pêşgir", "Pêşgir — a-, ne-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
1p9aq1xr2hsvy02hepng8c23uzrpm5t
6241584
6241583
2026-07-10T20:34:10Z
Wikihez
7344
6241584
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "Navdêr (îsm) — sêv, heywan, bextiyarî"],
["lêker", "Lêker (fiîl) — baz dan, xwarin, kirin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik, baş"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Bedirxan, Memo"],
["artîkel", "Artîkel — the, das, a"],
["baneşan", "Baneşan (nîda) — ox, ax, hey wax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu, em"],
["daçek", "Daçek (edat) — li, de, ji"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve, re"],
["paşgir", "Paşgir — -van, -ker, -lojî"],
["pêşdaçek", "Pêşdaçek — li, di, bi"],
["pêşgir", "Pêşgir — a-, ne-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
flv7jye1wmq27rlqks6800lxlvz0l86
6241585
6241584
2026-07-10T20:35:41Z
Wikihez
7344
6241585
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
// Bare POS types only — gender/transitivity are separate steps below.
// Navê duyem di navbeynê de nîşana term a hevwate ya erebî/osmanî ye,
// tenê ji bo ronîkirinê — mifteya rastîn (element[0]) neguherî ye,
// loma sernavên beşan û navên şablonan wek berê dimînin.
// Ji bo çend têgehên rêzimana rojavayî (curenav, girêdayîdaçek,
// navgir, pêş-/paşgir) di kevneşopiya rêzimana erebî-osmanî de
// hevwateyeke rasterast tuneye; ew bêyî parantêz hatine hiştin.
choices: [
["navdêr", "Navdêr (îsm) — sêv, heywan"],
["lêker", "Lêker (fiîl) — baz dan, xwarin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Memo,"],
["artîkel", "Artîkel — the, das"],
["baneşan", "Baneşan (nîda) — ox, ax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu"],
["daçek", "Daçek (edat) — li, de"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve"],
["paşgir", "Paşgir — -van, -lojî"],
["pêşdaçek", "Pêşdaçek — li, bi"],
["pêşgir", "Pêşgir — a-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koord", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
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({
mane: mane,
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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 += ".";
var out = "# " + 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);
out += wordLine("dijmane", sense.dijmane);
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
kyh5slghu39f7ftebsu4bkvkzx7iglu
6241586
6241585
2026-07-10T20:48:27Z
Wikihez
7344
6241586
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["navdêr", "Navdêr (îsm) — sêv, heywan"],
["lêker", "Lêker (fiîl) — baz dan, xwarin"],
["rengdêr", "Rengdêr (sifet) — sor, xweşik"],
["hoker", "Hoker (zerf) — zû, jêr, îro "],
["serenav", "Serenav (îsmê xisûsî) — Alî, Memo,"],
["artîkel", "Artîkel — the, das"],
["baneşan", "Baneşan (nîda) — ox, ax"],
["bazinedaçik", "Bazinedaçek — di...de"],
["cînav", "Cînav (zemîr) — ez, tu"],
["daçek", "Daçek (edat) — li, de"],
["girêdek", "Girêdek — û, feqat"],
["gotineke pêşiyan","Gotineke pêşiyan"],
["hejmar", "Hejmar — yek, didu"],
["hevok", "Hevok (cimle)"],
["îfade", "Îfade"],
["kurtenav", "Kurtenav"],
["navgir", "Navgir — -e-"],
["paşdaçek", "Paşdaçek — de, ve"],
["paşgir", "Paşgir — -van, -lojî"],
["pêşdaçek", "Pêşdaçek — li, bi"],
["pêşgir", "Pêşgir — a-, bê"],
["pirtik", "Pirtik"],
["reh", "Reh — -bêj-, -hêl-"],
["sembol", "Sembol"],
["tîp", "Tîp (herf) — X, W, Q"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
pl6xlo6at1sv7bqcgt96fu4masx2xgj
6241587
6241586
2026-07-10T20:53:13Z
Wikihez
7344
6241587
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
ri0bl7ixvoswjmotcxyupjx5wbxpy8h
6241588
6241587
2026-07-10T20:54:09Z
Wikihez
7344
6241588
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
ozqnu2wncmbk2pvpm4vghh1t671hd7p
6241590
6241588
2026-07-10T21:17:45Z
Wikihez
7344
6241590
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 === "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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
a632v4s2z7nwtbt1bjdhv8fysksseey
6241591
6241590
2026-07-10T21:33:22Z
Wikihez
7344
Restored revision 6241588 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]])
6241591
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── Preview checkbox ─────────────────────────────────────────────────
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();
var previewTimer = null;
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();
});
}, 400);
}
previewCheck.on("change", function () {
if ($(this).prop("checked")) {
schedulePreview();
} else {
clearTimeout(previewTimer);
previewPanel.hide();
}
});
// Listen on all input/change events on the form and update the preview.
startForm.on("input change", function () {
schedulePreview();
});
footer.append($("<span style='margin-left:1em'></span>")
.append(previewCheck).append(previewLabel));
startForm.append(footer);
$("#editform").hide().before(startForm);
// Insert preview panel after the form now that startForm is in the DOM.
startForm.after(previewPanel);
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"],
build);
});
//</nowiki>
ozqnu2wncmbk2pvpm4vghh1t671hd7p
6241592
6241591
2026-07-10T22:27:03Z
Wikihez
7344
6241592
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("+ Etîketê lê zêde bike");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
var subGroups = [
{ cls: "wiktvi-dfn-nimune", label: "Nimûne", rows: 2, narrow: false },
{ cls: "wiktvi-dfn-herwiha", label: "Herwiha", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-hevmane", label: "Hevmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-dijmane", label: "Dijmane", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-koordine", label: "Termên koordîne", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jornav", label: "Jornav", rows: 1, narrow: true },
{ cls: "wiktvi-dfn-jernav", label: "Jêrnav", rows: 1, narrow: true }
];
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
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);
});
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
r96nr72lm5l3vlxfn3a9xy0oxwd84gm
6241593
6241592
2026-07-10T22:31:51Z
Wikihez
7344
6241593
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 {" +
" display: inline-block;" +
" margin: 2px 0 6px;" +
" font-size: 0.85em;" +
"}" +
"input.wiktvi-dfn-label-field {" +
" display: block;" +
" width: 20em;" +
" max-width: 100%;" +
" box-sizing: border-box;" +
" margin-bottom: 6px;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Etîket (label) link + hidden field —
// {{e|lang|label1|label2}} tê danîn di navbera "#" û manê de.
// Bişkoja "+ Etîketê lê zêde bike" qutiya nivîsê vedike/dadixe;
// tişta hundir de bi "|" tê veqetandin (mînak: anatomî|heywan|û|Amed).
var labelToggle = $("<a href='#'></a>")
.addClass("wiktvi-dfn-label-toggle")
.text("(+ Etîket)");
var labelInput = $("<input type='text'>")
.addClass("wiktvi-dfn-label-field")
.attr("placeholder", "Etîketekê lê zêde bike wek: anatomî|heywan|û|Amed")
.hide();
labelToggle.on("click", function (evt) {
evt.preventDefault();
labelInput.toggle();
if (labelInput.is(":visible")) labelInput.focus();
});
block.append(labelToggle).append(labelInput);
// — Sub-field groups (nimûne, herwiha, hevmane, dijmane) —
// nimûne is always visible; the rest are hidden behind a click-to-add link.
var subGroups = [
{ 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 }
];
// Inline link row that holds all lazy-group triggers.
var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links");
$.each(subGroups, function (_, g) {
var groupDiv = $("<div></div>").addClass("wiktvi-dfn-subgroup " + g.cls + "-group");
if (!g.lazy) {
// Always-visible group (Nimûne) — original behaviour.
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 — show only a "(+ Label)" link; reveal the field on click.
var addLink = $("<a href='#'></a>")
.addClass("wiktvi-dfn-lazy-toggle")
.text("(+ " + g.label + ")");
addLink.on("click", function (evt) {
evt.preventDefault();
// Remove the link from the links row.
addLink.remove();
// Build the group inline.
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);
// Insert the group before the lazy-links row so order is preserved.
lazyLinksDiv.before(groupDiv);
firstInput.focus();
});
lazyLinksDiv.append(addLink).append(" ");
}
});
block.append(lazyLinksDiv);
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));
}
},
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 mane = $.trim(block.find("textarea.wiktvi-dfn-mane").val());
var etiket = $.trim(block.find("input.wiktvi-dfn-label-field").val());
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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
var labelTpl = "";
if (sense.etiket) {
var labelParts = $.grep(sense.etiket.split("|"), function (part) {
return $.trim(part) !== "";
}).map(function (part) {
return escapeTemplateParam($.trim(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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
cdpfmqikwvqdct7phle0rbod2yk50rj
6241594
6241593
2026-07-10T22:36:30Z
Wikihez
7344
6241594
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — Inline links row: (+ Etîket) + all lazy sub-group triggers —
// All lazy fields are revealed by clicking their respective link.
var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links");
// — Sub-field groups —
// nimûne: always visible.
// 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, isEtiket: 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).
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);
// Nimûne goes directly into the block, before the links row.
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 the links row to keep visual order.
lazyLinksDiv.before(groupDiv);
firstInput.focus();
});
lazyLinksDiv.append(addLink).append(" ");
}
});
block.append(lazyLinksDiv);
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));
}
},
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 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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
sdzz4tokms963wqe5k64bzsuvovkpii
6241595
6241594
2026-07-10T22:39:05Z
Wikihez
7344
6241595
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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 —
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);
});
block.append(dfnArea);
// — 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));
}
},
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 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({
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;
var hasMane = senses.some(function (s) { return s.mane !== ""; });
var text = $.map(senses, function (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}} — kesk parçeyên di navbera "|"
// de tên veqetandin, her yek jê tê revandin ji ber "=".
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;
}
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) {
return values.lang === "ku" && values.pos;
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
6exrqkagcjiibo6fdqgsneud2vu9wb3
6241596
6241595
2026-07-10T22:46:56Z
Wikihez
7344
6241596
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
var tplNames = [
"Guharto", "Hevmaneya", "Awayekî din", "Pirjimar",
"Romanization", "Awayê Jacobsonê",
"ku-Latn", "ku-Arab", "ckb-Latn", "ckb-Arab"
];
var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" }));
tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>"));
$.each(tplNames, function (_, name) {
tplSelect.append($("<option></option>").val(name).text(name));
});
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);
// — 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));
}
},
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);
});
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;
}
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
6o1zij34btw1o9siltu2vyxikjlwx55
6241597
6241596
2026-07-10T22:50:33Z
Wikihez
7344
6241597
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
var tplNames = [
"Guharto", "Hevmaneya", "Awayekî din", "Pirjimar",
"Romanization", "Awayê Jacobsonê",
"ku-Latn", "ku-Arab", "ckb-Latn", "ckb-Arab"
];
var tplSelect = $(mw.html.element("select", { "class": "wiktvi-dfn-tpl-select" }));
tplSelect.append($("<option value=''>— an şablonek hilbijêre —</option>"));
$.each(tplNames, function (_, name) {
tplSelect.append($("<option></option>").val(name).text(name));
});
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);
// — 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));
}
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
$.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;
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!");
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
qlnd24wyc2a82sm6xrtzisyyee7o11o
6241598
6241597
2026-07-10T22:56:46Z
Wikihez
7344
6241598
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;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
// langs: null = all languages, otherwise array of allowed lang codes.
var 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"] }
];
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));
}
},
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];
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
});
}
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;
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();
startForm.append(stepDiv);
});
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);
// ── 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"],
build);
});
//</nowiki>
7hmuf8illgbfgmco72cszlqmdrveuo3
6241599
6241598
2026-07-10T23:04:35Z
Wikihez
7344
6241599
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-pos-section {" +
" border-left: 3px solid #a2a9b1;" +
" margin-top: 1em;" +
" padding-left: 0.8em;" +
"}" +
".wiktvi-pos-section-header {" +
" display: flex;" +
" align-items: center;" +
" gap: 0.5em;" +
" margin-bottom: 0.3em;" +
" font-weight: bold;" +
" font-size: 0.9em;" +
" color: #555;" +
"}" +
"button.wiktvi-remove-section {" +
" font-size: 0.8em;" +
" padding: 1px 6px;" +
" cursor: pointer;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
// langs: null = all languages, otherwise array of allowed lang codes.
var 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"] }
];
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));
}
},
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];
// ── Extra sections (additional Cureyê rêzimanî blocks) ──────────────────
// Each extra section is a self-contained object built by createSection().
// It owns its own suffixed DOM IDs and step logic, and reads lang from
// section 0 via getSharedValues().
var extraSections = [];
function createSection(suffix, getSharedValues) {
// id() maps a bare step id to the suffixed DOM id used by this section.
function sid(id) { return id + suffix; }
function domId(id) { return "wiktvi-start-" + sid(id); }
function sel(id) { return "#" + domId(id); }
// Per-section makeWordListStep (references sec.steps for output values)
function secWordListStep(id, name, question_fmt, header, templateName) {
return {
id: sid(id),
name: name,
question_fmt: question_fmt,
multiple: true,
narrow: true,
visible: function (sv) { return sv.lang && sv[sid("pos")]; },
output: function (sv) {
var words = sv[sid(id)];
if (!words || !words.join("").length) return "";
return "==== " + header + " ====\n" + $.map(words, function (word) {
return word ? "* {{" + templateName + "|" + sv.lang + "|" +
escapeTemplateParam(word) + "}}" : undefined;
}).join("\n") + "\n\n";
}
};
}
var sec = {};
sec.steps = {
pos: {
id: sid("pos"),
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî yê "{{PAGENAME}}" çi ye?",
visible: function (sv) { return sv.lang; },
question_br: true,
choices: steps.pos.choices,
output: function (sv) {
var pos = sv[sid("pos")] || "";
var cinsiyet = sv[sid("cinsiyet")] || "";
var lekTur = sv[sid("lektur")] || "";
var capitalizedPos = capitalize(pos);
var outputString = "=== " + capitalizedPos + " ===\n";
var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" };
if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] &&
(pos === "navdêr" || pos === "serenav") && sv.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n";
}
outputString += "{{" + pos + "|" + sv.lang;
if (pos === "navdêr" || pos === "serenav") {
if (cinsiyet) { outputString += "|c=" + cinsiyet; }
else if (sv.lang === "ku") { outputString += "|c=?"; }
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (sv[sid("tr")]) { outputString += "|tr=" + escapeTemplateParam(sv[sid("tr")]); }
outputString += "}}\n";
return outputString;
}
},
cinsiyet: {
id: sid("cinsiyet"),
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (sv) {
var meta = metadata[sv.lang];
return !!(sv.lang && (sv[sid("pos")] === "navdêr" || sv[sid("pos")] === "serenav") &&
meta && meta.g && meta.g.length);
},
build: function (stepDiv, sv) {
var select = stepDiv.find("select.wiktvi-start-step-field");
if (!select.length) {
select = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: domId("cinsiyet") + "-field" }));
stepDiv.append(select);
}
if (!sv) return select;
var meta = metadata[sv.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 ""; }
},
lektur: {
id: sid("lektur"),
name: "Cureyê lêkerê",
question_fmt: "Cureyê lêkerê çi ye?",
question_br: true,
visible: function (sv) {
return sv.lang && sv[sid("pos")] && /^lêker/.test(sv[sid("pos")]);
},
choices: steps.lektur.choices,
output: function () { return ""; }
},
tr: {
id: sid("tr"),
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona kelîmeyê",
multiple: false,
narrow: true,
visible: function (sv) {
return sv.lang && sv[sid("pos")] && needsTransliteration(sv.lang);
}
},
dfn: {
id: sid("dfn"),
name: "Mane",
question_fmt: "Mane û nimûneyên kelîmeyê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (sv) { return sv.lang && sv[sid("pos")]; },
example: steps.dfn.example,
buildSenseBlock: function (stepDiv) {
// Reuse the shared buildSenseBlock but with this section's getValues
// for tplSelect's updateTplOptions.
var block = $("<li class='wiktvi-dfn-sense'></li>");
var dfnArea = $("<textarea></textarea>")
.attr("class", "wiktvi-start-step-field wiktvi-dfn-mane")
.attr("rows", 3).attr("placeholder", "Mane…");
dfnArea.on("input", function () {
sec.steps.dfn.onDfnInput(stepDiv, block, this);
});
var 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"] }
];
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(",") : ""));
});
var tplTitleInput = $("<input type='text'>")
.addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow")
.attr("placeholder", "Navê rûpelê…").hide();
function updateTplOptions() {
var lang = sec.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("");
}
}
tplSelect.data("updateOptions", updateTplOptions);
tplSelect.on("change", function () {
var chosen = $(this).val();
if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); }
else { dfnArea.show(); tplTitleInput.hide().val(""); }
sec.refresh();
});
var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row")
.append(tplSelect).append(" ").append(tplTitleInput);
block.append(tplRow).append(dfnArea);
updateTplOptions();
var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links");
block.append(lazyLinksDiv);
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) {
var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": ");
var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list");
var fi = $("<textarea></textarea>").attr("rows", g.rows)
.attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : ""));
fi.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); });
list.append($("<li></li>").append(fi));
groupDiv.append(lbl).append(list);
block.append(groupDiv);
} else {
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 fi = $("<textarea></textarea>").attr("rows", g.rows)
.attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow");
fi.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); });
list.append($("<li></li>").append(fi));
groupDiv.append(lbl).append(list);
block.find(".wiktvi-dfn-nimune-group").before(groupDiv);
fi.focus();
});
lazyLinksDiv.append(addLink).append(" ");
}
});
return block;
},
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) { list.append(sec.steps.dfn.buildSenseBlock(stepDiv)); }
sec.refresh();
},
onSubInput: steps.dfn.onSubInput,
build: function (stepDiv) {
if (stepDiv.find("ol.wiktvi-dfn-list").length) return null;
var list = $("<ol class='wiktvi-dfn-list'></ol>");
list.append(sec.steps.dfn.buildSenseBlock(stepDiv));
stepDiv.append(list);
return null;
},
getSenses: steps.dfn.getSenses,
getOutput: function (sv, callback) {
var stepDiv = $(sel("dfn"));
var senses = sec.steps.dfn.getSenses(stepDiv);
var lang = sv.lang;
var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); });
var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; });
var text = $.map(senses, function (sense) {
if (sense.tpl) {
if (!sense.tplTitle) return undefined;
return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}";
}
var dfn = sense.mane;
if (!dfn) return undefined;
if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn);
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
var labelTpl = "";
if (sense.etiket && sense.etiket.length) {
var lp = sense.etiket.map(function (p) { return escapeTemplateParam($.trim(p)); })
.filter(function (p) { return p !== ""; });
if (lp.length) labelTpl = " {{e|" + lang + "|" + lp.join("|") + "}} ";
}
var out = "#" + (labelTpl ? labelTpl : " ") + dfn;
out += formatNimune(sense.nimune, lang);
function wl(tpl, words) {
if (!words.length) return "";
return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}";
}
out += wl("herwiha-rêz", sense.herwiha);
out += wl("hevmane", sense.hevmane);
out += wl("dijmane", sense.dijmane);
out += wl("termên koordîne", sense.koordine);
out += wl("jornav", sense.jornav);
out += wl("jêrnav", sense.jernav);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n";
callback(text); return;
}
if (!hasRegularMane) { callback(text); return; }
var done = function () { $.wiktviLinkify(text, callback); };
mw.loader.using("ext.gadget.linkify", done, done);
}
},
je: secWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"),
tekildar: secWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"),
binereherwiha: secWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"),
etym: {
id: sid("etym"),
name: "etîmolojî",
visible: function () { return false; },
output: function (sv) {
return sv.lang === "ku" ? "==== Etîmolojî ====\n{{ji?|ku}}" : "";
}
},
trans: {
id: sid("trans"),
name: "werger",
visible: function (sv) {
if (!(sv.lang === "ku" && sv[sid("pos")])) return false;
var hasTpl = false;
$(sel("dfn") + " li.wiktvi-dfn-sense").each(function () {
if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTpl = true; return false; }
});
return !hasTpl;
},
disabledKeys: { "navz": true, "ku": true },
buildRow: function (stepDiv) {
var row = $("<li class='wiktvi-trans-row'></li>");
var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" }));
langSel.attr("data-placeholder", "Zimanekî hilbijêre");
populateMenus(langSel, sec.steps.trans.keys || [], sec.steps.trans.disabledKeys);
langSel.on("change", function () { sec.steps.trans.onLangChange(stepDiv, row); });
var wordList = $("<ul class='wiktvi-trans-words'></ul>");
wordList.append($("<li></li>").append(sec.steps.trans.makeWordInput()));
if (isMobile) row.append(wrapNativeSelect(langSel)).append(wordList);
else row.append(langSel).append(wordList);
return row;
},
makeWordInput: steps.trans.makeWordInput,
onLangChange: function (stepDiv, row) {
var list = stepDiv.find("ul.wiktvi-trans-list");
if (row.is(list.children("li.wiktvi-trans-row:last-child"))) {
var nr = sec.steps.trans.buildRow(stepDiv);
list.append(nr);
if (!isMobile) nr.find("select").chosen(chosenOptions);
}
sec.steps.trans.syncDisabledKeys(stepDiv);
},
syncDisabledKeys: steps.trans.syncDisabledKeys,
build: function (stepDiv) {
if (stepDiv.find("ul.wiktvi-trans-list").length) return null;
var list = $("<ul class='wiktvi-trans-list'></ul>");
list.append(sec.steps.trans.buildRow(stepDiv));
stepDiv.append(list);
if (!isMobile) list.find("select").chosen(chosenOptions);
return null;
},
getTranslations: steps.trans.getTranslations,
output: function (sv) {
if (sv.lang !== "ku") return "";
var stepDiv = $(sel("trans"));
var rows = steps.trans.getTranslations(stepDiv);
var out = "\n\n==== Werger ====\n{{werger-ser}}";
if (rows.length) {
rows.sort(function (a, b) {
return (langsByCode[a[0]] && langsByCode[a[0]][2] || "")
.localeCompare((langsByCode[b[0]] && langsByCode[b[0]][2] || ""), "ku");
});
out += "\n" + $.map(rows, function (row) {
return "* {{Z|" + row[0] + "}}: " + row[1].map(escapeTemplateParam)
.map(function (w) { return "{{W|" + row[0] + "|" + w + "}}"; }).join(", ");
}).join("\n");
}
out += "\n{{werger-bin}}\n\n";
return out;
}
}
};
sec.steps.trans.keys = steps.trans.keys;
sec.orderedSteps = [
sec.steps.pos, sec.steps.cinsiyet, sec.steps.lektur, sec.steps.tr,
sec.steps.dfn, sec.steps.je, sec.steps.tekildar, sec.steps.binereherwiha,
sec.steps.etym, sec.steps.trans
];
// Per-section getValues — merges shared lang into its own step values.
sec.getValues = function () {
var sv = $.extend({}, getSharedValues());
$.each(sec.steps, function (_, step) {
var fields = $(sel(step.id.replace(suffix, "")) + " .wiktvi-start-step-field");
// For steps with a custom id already suffixed, use the full id DOM selector.
fields = $("#" + "wiktvi-start-" + step.id + " .wiktvi-start-step-field");
if (step.keys) {
var vals = {};
fields.each(function (i, field) {
var key = $(field).prevAll(".wiktvi-start-step-keyfield").val();
if (key) vals[key] = $(field).val();
});
sv[step.id] = vals;
} else if (step.multiple) {
sv[step.id] = fields.map(function () { return $(this).val(); }).get();
} else {
sv[step.id] = fields.val();
}
});
return sv;
};
// Per-section refresh — updates visibility and builds for this section's steps only.
sec.refresh = function () {
var sv = sec.getValues();
$(sel("dfn") + " .wiktvi-dfn-tpl-select").each(function () {
var fn = $(this).data("updateOptions");
if (typeof fn === "function") fn();
});
$.each(sec.steps, function (_, step) {
var stepDiv = $("#wiktvi-start-" + step.id);
if (typeof step.visible === "function" && !step.visible(sv)) {
stepDiv.slideUp();
} else {
if (typeof step.build === "function") {
prepareInput(step.build(stepDiv, sv), step);
}
var input = stepDiv.find(".wiktvi-start-step-field");
if (typeof step.example === "function") {
input.attr("placeholder", step.example(sv) || "");
}
stepDiv.slideDown();
}
});
};
// Builds the section DOM block and appends it to the form.
sec.buildDOM = function (startForm) {
var wrapper = $("<div></div>")
.addClass("wiktvi-pos-section")
.attr("id", "wiktvi-pos-section" + suffix);
var header = $("<div></div>").addClass("wiktvi-pos-section-header");
header.append("Beşa din — Cureyê rêzimanî");
var removeBtn = $("<button type='button'></button>")
.addClass("wiktvi-remove-section").text("× Rake");
removeBtn.on("click", function () {
wrapper.remove();
extraSections = $.grep(extraSections, function (s) { return s !== sec; });
});
header.append(removeBtn);
wrapper.append(header);
$.each(sec.orderedSteps, function (_, 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;
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);
} else if (typeof step.build === "function") {
input = step.build(stepDiv);
} 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);
}
}
if (input) {
if (step.required) input.prop("required", true);
// On change, run this section's own refresh.
input.on("change", function () { sec.refresh(); });
}
stepDiv.hide();
wrapper.append(stepDiv);
});
startForm.find("#wiktvi-start-footer").before(wrapper);
if (!isMobile) wrapper.find("select.wiktvi-start-step-field").chosen(chosenOptions);
// Listen to all input/change inside the section wrapper.
wrapper.on("input change", function () { sec.refresh(); });
sec.refresh();
};
// Produces the wikitext for this section (chained async via callback).
sec.getOutput = function (callback) {
var sv = sec.getValues();
if (!sv[sid("pos")]) { callback(""); return; }
var entry = sec.steps.pos.output(sv);
sec.steps.dfn.getOutput(sv, function (dfnOut) {
entry += dfnOut;
entry += sec.steps.je.output(sv);
entry += sec.steps.tekildar.output(sv);
entry += sec.steps.binereherwiha.output(sv);
entry += sec.steps.etym.output(sv);
entry += sec.steps.trans.output(sv);
callback(entry);
});
};
return sec;
}
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
// Chain extra sections sequentially then fire callback.
function appendExtraSections(idx) {
if (idx >= extraSections.length) {
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
return;
}
extraSections[idx].getOutput(function (secOut) {
entry += secOut;
appendExtraSections(idx + 1);
});
}
appendExtraSections(0);
});
}
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");
// Propagate lang change to all extra sections.
$.each(extraSections, function (_, sec) { sec.refresh(); });
}
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;
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();
startForm.append(stepDiv);
});
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);
var addSectionBtn = $(mw.html.element("button", {
id: "wiktvi-add-section",
type: "button" }, "+ Beşa din lê zêde bike"));
addSectionBtn.css("margin-left", "6px");
addSectionBtn.on("click", function () {
var suffix = "_s" + (extraSections.length + 2);
var sec = createSection(suffix, getValues);
extraSections.push(sec);
sec.buildDOM(startForm);
});
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"],
build);
});
//</nowiki>
dp8vyzj77hp8s3d6mqgqhg1fhbvqbcs
6241600
6241599
2026-07-10T23:07:59Z
Wikihez
7344
6241600
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-pos-section {" +
" border-left: 3px solid #a2a9b1;" +
" margin-top: 1em;" +
" padding-left: 0.8em;" +
"}" +
".wiktvi-pos-section-header {" +
" display: flex;" +
" align-items: center;" +
" gap: 0.5em;" +
" margin-bottom: 0.3em;" +
" font-weight: bold;" +
" font-size: 0.9em;" +
" color: #555;" +
"}" +
"button.wiktvi-remove-section {" +
" font-size: 0.8em;" +
" padding: 1px 6px;" +
" cursor: pointer;" +
"}"
);
// 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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
// langs: null = all languages, otherwise array of allowed lang codes.
var 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"] }
];
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));
}
},
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];
// ── Extra sections (additional Cureyê rêzimanî blocks) ──────────────────
// Each extra section is a self-contained object built by createSection().
// It owns its own suffixed DOM IDs and step logic, and reads lang from
// section 0 via getSharedValues().
var extraSections = [];
function createSection(suffix, getSharedValues) {
// id() maps a bare step id to the suffixed DOM id used by this section.
function sid(id) { return id + suffix; }
function domId(id) { return "wiktvi-start-" + sid(id); }
function sel(id) { return "#" + domId(id); }
// Per-section makeWordListStep (references sec.steps for output values)
function secWordListStep(id, name, question_fmt, header, templateName) {
return {
id: sid(id),
name: name,
question_fmt: question_fmt,
multiple: true,
narrow: true,
visible: function (sv) { return sv.lang && sv[sid("pos")]; },
output: function (sv) {
var words = sv[sid(id)];
if (!words || !words.join("").length) return "";
return "==== " + header + " ====\n" + $.map(words, function (word) {
return word ? "* {{" + templateName + "|" + sv.lang + "|" +
escapeTemplateParam(word) + "}}" : undefined;
}).join("\n") + "\n\n";
}
};
}
var sec = {};
sec.steps = {
pos: {
id: sid("pos"),
required: true,
name: "Cureyê rêzimanî",
question_fmt: "Cureyê rêzimanî yê '{{PAGENAME}}' çi ye?",
visible: function (sv) { return sv.lang; },
question_br: true,
choices: steps.pos.choices,
output: function (sv) {
var pos = sv[sid("pos")] || "";
var cinsiyet = sv[sid("cinsiyet")] || "";
var lekTur = sv[sid("lektur")] || "";
var capitalizedPos = capitalize(pos);
var outputString = "=== " + capitalizedPos + " ===\n";
var genderNames = { m: "mê", n: "nêr", mn: "mê û nêr" };
if (!pageName.includes(" ") && cinsiyet && genderNames[cinsiyet] &&
(pos === "navdêr" || pos === "serenav") && sv.lang === "ku") {
outputString += "{{ku-tewîn-nav|" + pageName + "|" + genderNames[cinsiyet] + "}}\n";
}
outputString += "{{" + pos + "|" + sv.lang;
if (pos === "navdêr" || pos === "serenav") {
if (cinsiyet) { outputString += "|c=" + cinsiyet; }
else if (sv.lang === "ku") { outputString += "|c=?"; }
} else if (/^lêker/.test(pos) && lekTur) {
outputString += "|c=" + lekTur;
}
if (sv[sid("tr")]) { outputString += "|tr=" + escapeTemplateParam(sv[sid("tr")]); }
outputString += "}}\n";
return outputString;
}
},
cinsiyet: {
id: sid("cinsiyet"),
name: "cinsiyet",
question_fmt: "Cinsiyeta kelîmeyê çi ye?",
question_br: true,
visible: function (sv) {
var meta = metadata[sv.lang];
return !!(sv.lang && (sv[sid("pos")] === "navdêr" || sv[sid("pos")] === "serenav") &&
meta && meta.g && meta.g.length);
},
build: function (stepDiv, sv) {
var select = stepDiv.find("select.wiktvi-start-step-field");
if (!select.length) {
select = $(mw.html.element("select", {
"class": "wiktvi-start-step-field",
id: domId("cinsiyet") + "-field" }));
stepDiv.append(select);
}
if (!sv) return select;
var meta = metadata[sv.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 ""; }
},
lektur: {
id: sid("lektur"),
name: "Cureyê lêkerê",
question_fmt: "Cureyê lêkerê çi ye?",
question_br: true,
visible: function (sv) {
return sv.lang && sv[sid("pos")] && /^lêker/.test(sv[sid("pos")]);
},
choices: steps.lektur.choices,
output: function () { return ""; }
},
tr: {
id: sid("tr"),
name: "transkrîpsiyon",
question_fmt: "Transkrîpsiyona kelîmeyê",
multiple: false,
narrow: true,
visible: function (sv) {
return sv.lang && sv[sid("pos")] && needsTransliteration(sv.lang);
}
},
dfn: {
id: sid("dfn"),
name: "Mane",
question_fmt: "Mane û nimûneyên kelîmeyê binivîse.",
multiple: true,
ordered: true,
rows: 3,
visible: function (sv) { return sv.lang && sv[sid("pos")]; },
example: steps.dfn.example,
buildSenseBlock: function (stepDiv) {
// Reuse the shared buildSenseBlock but with this section's getValues
// for tplSelect's updateTplOptions.
var block = $("<li class='wiktvi-dfn-sense'></li>");
var dfnArea = $("<textarea></textarea>")
.attr("class", "wiktvi-start-step-field wiktvi-dfn-mane")
.attr("rows", 3).attr("placeholder", "Mane…");
dfnArea.on("input", function () {
sec.steps.dfn.onDfnInput(stepDiv, block, this);
});
var 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"] }
];
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(",") : ""));
});
var tplTitleInput = $("<input type='text'>")
.addClass("wiktvi-dfn-tpl-title wiktvi-start-narrow")
.attr("placeholder", "Navê rûpelê…").hide();
function updateTplOptions() {
var lang = sec.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("");
}
}
tplSelect.data("updateOptions", updateTplOptions);
tplSelect.on("change", function () {
var chosen = $(this).val();
if (chosen) { dfnArea.hide(); tplTitleInput.show().focus(); }
else { dfnArea.show(); tplTitleInput.hide().val(""); }
sec.refresh();
});
var tplRow = $("<div></div>").addClass("wiktvi-dfn-tpl-row")
.append(tplSelect).append(" ").append(tplTitleInput);
block.append(tplRow).append(dfnArea);
updateTplOptions();
var lazyLinksDiv = $("<div></div>").addClass("wiktvi-dfn-lazy-links");
block.append(lazyLinksDiv);
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) {
var lbl = $("<span></span>").addClass("wiktvi-dfn-sublabel").text(g.label + ": ");
var list = $("<ol></ol>").addClass("wiktvi-dfn-sublist " + g.cls + "-list");
var fi = $("<textarea></textarea>").attr("rows", g.rows)
.attr("class", "wiktvi-dfn-subfield" + (g.narrow ? " wiktvi-start-narrow" : ""));
fi.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, g.narrow); });
list.append($("<li></li>").append(fi));
groupDiv.append(lbl).append(list);
block.append(groupDiv);
} else {
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 fi = $("<textarea></textarea>").attr("rows", g.rows)
.attr("class", "wiktvi-dfn-subfield wiktvi-start-narrow");
fi.on("input", function () { steps.dfn.onSubInput(list, this, g.rows, true); });
list.append($("<li></li>").append(fi));
groupDiv.append(lbl).append(list);
block.find(".wiktvi-dfn-nimune-group").before(groupDiv);
fi.focus();
});
lazyLinksDiv.append(addLink).append(" ");
}
});
return block;
},
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) { list.append(sec.steps.dfn.buildSenseBlock(stepDiv)); }
sec.refresh();
},
onSubInput: steps.dfn.onSubInput,
build: function (stepDiv) {
if (stepDiv.find("ol.wiktvi-dfn-list").length) return null;
var list = $("<ol class='wiktvi-dfn-list'></ol>");
list.append(sec.steps.dfn.buildSenseBlock(stepDiv));
stepDiv.append(list);
return null;
},
getSenses: steps.dfn.getSenses,
getOutput: function (sv, callback) {
var stepDiv = $(sel("dfn"));
var senses = sec.steps.dfn.getSenses(stepDiv);
var lang = sv.lang;
var hasMane = senses.some(function (s) { return s.mane !== "" || (s.tpl && s.tplTitle); });
var hasRegularMane = senses.some(function (s) { return !s.tpl && s.mane !== ""; });
var text = $.map(senses, function (sense) {
if (sense.tpl) {
if (!sense.tplTitle) return undefined;
return "# {{" + sense.tpl + "|" + lang + "|" + escapeTemplateParam(sense.tplTitle) + "}}";
}
var dfn = sense.mane;
if (!dfn) return undefined;
if (dfn[0] !== dfn[0].toUpperCase()) dfn = capitalize(dfn);
if (!dfn.match(/[.…?!)\]]$/)) dfn += ".";
var labelTpl = "";
if (sense.etiket && sense.etiket.length) {
var lp = sense.etiket.map(function (p) { return escapeTemplateParam($.trim(p)); })
.filter(function (p) { return p !== ""; });
if (lp.length) labelTpl = " {{e|" + lang + "|" + lp.join("|") + "}} ";
}
var out = "#" + (labelTpl ? labelTpl : " ") + dfn;
out += formatNimune(sense.nimune, lang);
function wl(tpl, words) {
if (!words.length) return "";
return "\n#: {{" + tpl + "|" + lang + "|" + words.map(escapeTemplateParam).join("|") + "}}";
}
out += wl("herwiha-rêz", sense.herwiha);
out += wl("hevmane", sense.hevmane);
out += wl("dijmane", sense.dijmane);
out += wl("termên koordîne", sense.koordine);
out += wl("jornav", sense.jornav);
out += wl("jêrnav", sense.jernav);
return out;
}).join("\n") + "\n\n";
if (!hasMane) {
text = "# {{mane?|" + lang + "}}\n#* {{bênimûne|" + lang + "}}\n\n";
callback(text); return;
}
if (!hasRegularMane) { callback(text); return; }
var done = function () { $.wiktviLinkify(text, callback); };
mw.loader.using("ext.gadget.linkify", done, done);
}
},
je: secWordListStep("je", "jê", "Kelîmeyên jê çêbûyî binivîse", "Jê", "g"),
tekildar: secWordListStep("tekildar", "têkildar", "Kelîmeyên têkildarî vê kelîmeyê binivîse", "Têkildar", "g"),
binereherwiha: secWordListStep("binereherwiha", "binêre herwiha", "Kelîmeyên din ên eleqedar binivîse", "Binêre herwiha", "g"),
etym: {
id: sid("etym"),
name: "etîmolojî",
visible: function () { return false; },
output: function (sv) {
return sv.lang === "ku" ? "==== Etîmolojî ====\n{{ji?|ku}}" : "";
}
},
trans: {
id: sid("trans"),
name: "werger",
visible: function (sv) {
if (!(sv.lang === "ku" && sv[sid("pos")])) return false;
var hasTpl = false;
$(sel("dfn") + " li.wiktvi-dfn-sense").each(function () {
if ($(this).find("select.wiktvi-dfn-tpl-select").val()) { hasTpl = true; return false; }
});
return !hasTpl;
},
disabledKeys: { "navz": true, "ku": true },
buildRow: function (stepDiv) {
var row = $("<li class='wiktvi-trans-row'></li>");
var langSel = $(mw.html.element("select", { "class": "wiktvi-start-step-keyfield wiktvi-start-narrow" }));
langSel.attr("data-placeholder", "Zimanekî hilbijêre");
populateMenus(langSel, sec.steps.trans.keys || [], sec.steps.trans.disabledKeys);
langSel.on("change", function () { sec.steps.trans.onLangChange(stepDiv, row); });
var wordList = $("<ul class='wiktvi-trans-words'></ul>");
wordList.append($("<li></li>").append(sec.steps.trans.makeWordInput()));
if (isMobile) row.append(wrapNativeSelect(langSel)).append(wordList);
else row.append(langSel).append(wordList);
return row;
},
makeWordInput: steps.trans.makeWordInput,
onLangChange: function (stepDiv, row) {
var list = stepDiv.find("ul.wiktvi-trans-list");
if (row.is(list.children("li.wiktvi-trans-row:last-child"))) {
var nr = sec.steps.trans.buildRow(stepDiv);
list.append(nr);
if (!isMobile) nr.find("select").chosen(chosenOptions);
}
sec.steps.trans.syncDisabledKeys(stepDiv);
},
syncDisabledKeys: steps.trans.syncDisabledKeys,
build: function (stepDiv) {
if (stepDiv.find("ul.wiktvi-trans-list").length) return null;
var list = $("<ul class='wiktvi-trans-list'></ul>");
list.append(sec.steps.trans.buildRow(stepDiv));
stepDiv.append(list);
if (!isMobile) list.find("select").chosen(chosenOptions);
return null;
},
getTranslations: steps.trans.getTranslations,
output: function (sv) {
if (sv.lang !== "ku") return "";
var stepDiv = $(sel("trans"));
var rows = steps.trans.getTranslations(stepDiv);
var out = "\n\n==== Werger ====\n{{werger-ser}}";
if (rows.length) {
rows.sort(function (a, b) {
return (langsByCode[a[0]] && langsByCode[a[0]][2] || "")
.localeCompare((langsByCode[b[0]] && langsByCode[b[0]][2] || ""), "ku");
});
out += "\n" + $.map(rows, function (row) {
return "* {{Z|" + row[0] + "}}: " + row[1].map(escapeTemplateParam)
.map(function (w) { return "{{W|" + row[0] + "|" + w + "}}"; }).join(", ");
}).join("\n");
}
out += "\n{{werger-bin}}\n\n";
return out;
}
}
};
sec.steps.trans.keys = steps.trans.keys;
sec.orderedSteps = [
sec.steps.pos, sec.steps.cinsiyet, sec.steps.lektur, sec.steps.tr,
sec.steps.dfn, sec.steps.je, sec.steps.tekildar, sec.steps.binereherwiha,
sec.steps.etym, sec.steps.trans
];
// Per-section getValues — merges shared lang into its own step values.
sec.getValues = function () {
var sv = $.extend({}, getSharedValues());
$.each(sec.steps, function (_, step) {
var fields = $(sel(step.id.replace(suffix, "")) + " .wiktvi-start-step-field");
// For steps with a custom id already suffixed, use the full id DOM selector.
fields = $("#" + "wiktvi-start-" + step.id + " .wiktvi-start-step-field");
if (step.keys) {
var vals = {};
fields.each(function (i, field) {
var key = $(field).prevAll(".wiktvi-start-step-keyfield").val();
if (key) vals[key] = $(field).val();
});
sv[step.id] = vals;
} else if (step.multiple) {
sv[step.id] = fields.map(function () { return $(this).val(); }).get();
} else {
sv[step.id] = fields.val();
}
});
return sv;
};
// Per-section refresh — updates visibility and builds for this section's steps only.
sec.refresh = function () {
var sv = sec.getValues();
$(sel("dfn") + " .wiktvi-dfn-tpl-select").each(function () {
var fn = $(this).data("updateOptions");
if (typeof fn === "function") fn();
});
$.each(sec.steps, function (_, step) {
var stepDiv = $("#wiktvi-start-" + step.id);
if (typeof step.visible === "function" && !step.visible(sv)) {
stepDiv.slideUp();
} else {
if (typeof step.build === "function") {
prepareInput(step.build(stepDiv, sv), step);
}
var input = stepDiv.find(".wiktvi-start-step-field");
if (typeof step.example === "function") {
input.attr("placeholder", step.example(sv) || "");
}
stepDiv.slideDown();
}
});
};
// Builds the section DOM block and appends it to the form.
sec.buildDOM = function (startForm) {
var wrapper = $("<div></div>")
.addClass("wiktvi-pos-section")
.attr("id", "wiktvi-pos-section" + suffix);
var header = $("<div></div>").addClass("wiktvi-pos-section-header");
header.append("Beşa din — Cureyê rêzimanî");
var removeBtn = $("<button type='button'></button>")
.addClass("wiktvi-remove-section").text("× Rake");
removeBtn.on("click", function () {
wrapper.remove();
extraSections = $.grep(extraSections, function (s) { return s !== sec; });
});
header.append(removeBtn);
wrapper.append(header);
$.each(sec.orderedSteps, function (_, 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;
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);
} else if (typeof step.build === "function") {
input = step.build(stepDiv);
} 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);
}
}
if (input) {
if (step.required) input.prop("required", true);
// On change, run this section's own refresh.
input.on("change", function () { sec.refresh(); });
}
stepDiv.hide();
wrapper.append(stepDiv);
});
startForm.find("#wiktvi-start-footer").before(wrapper);
if (!isMobile) wrapper.find("select.wiktvi-start-step-field").chosen(chosenOptions);
// Listen to all input/change inside the section wrapper.
wrapper.on("input change", function () { sec.refresh(); });
sec.refresh();
};
// Produces the wikitext for this section (chained async via callback).
sec.getOutput = function (callback) {
var sv = sec.getValues();
if (!sv[sid("pos")]) { callback(""); return; }
var entry = sec.steps.pos.output(sv);
sec.steps.dfn.getOutput(sv, function (dfnOut) {
entry += dfnOut;
entry += sec.steps.je.output(sv);
entry += sec.steps.tekildar.output(sv);
entry += sec.steps.binereherwiha.output(sv);
entry += sec.steps.etym.output(sv);
entry += sec.steps.trans.output(sv);
callback(entry);
});
};
return sec;
}
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 getWikitext(callback) {
var values = getValues();
var entry = steps.lang.output(values);
entry += steps.pron.output(values);
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);
// Chain extra sections sequentially then fire callback.
function appendExtraSections(idx) {
if (idx >= extraSections.length) {
var senses = steps.dfn.getSenses($("#wiktvi-start-dfn"));
var dfnSummary = senses.map(function (s) { return s.mane; }).filter(Boolean).join("; ");
var summary = "([[Mediawiki:Gadget-start.js|WF:Nû]]) +" + values.lang + ":" + values.pos + ":" + dfnSummary;
document.getElementById("wpSummary").value = summary;
callback(entry);
return;
}
extraSections[idx].getOutput(function (secOut) {
entry += secOut;
appendExtraSections(idx + 1);
});
}
appendExtraSections(0);
});
}
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");
// Propagate lang change to all extra sections.
$.each(extraSections, function (_, sec) { sec.refresh(); });
}
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;
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();
startForm.append(stepDiv);
});
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);
var addSectionBtn = $(mw.html.element("button", {
id: "wiktvi-add-section",
type: "button" }, "+ Beşa din lê zêde bike"));
addSectionBtn.css("margin-left", "6px");
addSectionBtn.on("click", function () {
var suffix = "_s" + (extraSections.length + 2);
var sec = createSection(suffix, getValues);
extraSections.push(sec);
sec.buildDOM(startForm);
});
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"],
build);
});
//</nowiki>
3lrlusio1cwzc291ssy9c4inx6dh9ht
6241601
6241600
2026-07-10T23:23:33Z
Wikihez
7344
6241601
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 = {};
var 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}};
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,
choices: [
// Languages with 100 or more entries are loaded immediately.
// The rest come in through [[MediaWiki:Gadget-translation_editor.js/ziman.json]].
["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î"] ],
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,
choices: [
["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)"] ],
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) —
// langs: null = all languages, otherwise array of allowed lang codes.
var 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"] }
];
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));
}
},
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"],
build);
});
//</nowiki>
5ruccnws9r5kr3fa2sx86y1j72bzx3b
Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js
2
1325562
6241568
6101182
2026-07-10T18:40:11Z
Wikihez
7344
6241568
javascript
text/javascript
// {{documentation}} [[en:MediaWiki:Gadget-TranslationAdder-Data.js]]
// <nowiki>
// implicit dependencies : ext.gadget.LanguageUtils
/* jshint maxerr:1048576, strict:true, undef:true, latedef:true, es5:true */
/* global $, ScriptUtils, mw */
window.LangMetadata = function() {
//Singleton
if (arguments.callee.instance)
return arguments.callee.instance;
else
arguments.callee.instance = this;
// {{{ Metadata dictionaries
// FIXME: Is it possible to query this information directly from [[Module:languages]]?
var 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"
},
// modelling on cmn, nb, prs
"fa-cls": {
wiktprefix: "fa",
sc: "Arab",
wsc: "fa-Arab"
},
// modelling on cmn, nb, prs
"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", "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
}, // script should include "Geok" for Asomtavruli & Nuskhuri but prevents automatic transliteration?
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
}
};
var clean = {
aar: "aa",
afar: "aa",
abk: "ab",
abkhazian: "ab",
afr: "af",
afrikaans: "af",
aka: "ak",
akan: "ak",
amh: "am",
amharic: "am",
ara: "ar",
arabic: "ar",
arg: "an",
aragonese: "an",
asm: "as",
assamese: "as",
ava: "av",
avaric: "av",
ave: "ae",
avestan: "ae",
aym: "ay",
aymara: "ay",
aze: "az",
azerbaijani: "az",
bak: "ba",
bashkir: "ba",
bam: "bm",
bambara: "bm",
bel: "be",
belarusian: "be",
ben: "bn",
bengali: "bn",
bis: "bi",
bislama: "bi",
bod: "bo",
tibetan: "bo",
bs: "sh",
bos: "sh",
bosnian: "sh",
bre: "br",
breton: "br",
bul: "bg",
bulgarian: "bg",
cat: "ca",
catalan: "ca",
ces: "cs",
czech: "cs",
cha: "ch",
chamorro: "ch",
che: "ce",
chechen: "ce",
chu: "cu",
churchslavic: "cu",
chv: "cv",
chuvash: "cv",
cor: "kw",
cornish: "kw",
cos: "co",
corsican: "co",
cre: "cr",
cree: "cr",
cym: "cy",
welsh: "cy",
dan: "da",
danish: "da",
deu: "de",
german: "de",
div: "dv",
dhivehi: "dv",
dzo: "dz",
dzongkha: "dz",
ekk: "et",
ell: "el",
greek: "el",
eng: "en",
english: "en",
epo: "eo",
esperanto: "eo",
est: "et",
estonian: "et",
eus: "eu",
basque: "eu",
ewe: "ee",
fao: "fo",
faroese: "fo",
fas: "fa",
//"fa-ira": "fa",
//"fa-cls": "fa",
//prs: "fa",
persian: "fa",
fij: "fj",
fijian: "fj",
fil: "tl",
fin: "fi",
finnish: "fi",
fra: "fr",
french: "fr",
fry: "fy",
westernfrisian: "fy",
ful: "ff",
fulah: "ff",
gla: "gd",
scottishgaelic: "gd",
gle: "ga",
irish: "ga",
glg: "gl",
galician: "gl",
glv: "gv",
manx: "gv",
grn: "gn",
guarani: "gn",
guj: "gu",
gujarati: "gu",
hat: "ht",
haitian: "ht",
hau: "ha",
hausa: "ha",
heb: "he",
hebrew: "he",
her: "hz",
herero: "hz",
hin: "hi",
hindi: "hi",
hmo: "ho",
hirimotu: "ho",
hr: "sh",
hrv: "sh",
croatian: "sh",
hun: "hu",
hungarian: "hu",
hye: "hy",
armenian: "hy",
ibo: "ig",
igbo: "ig",
ido: "io",
iii: "ii",
sichuanyi: "ii",
iku: "iu",
inuktitut: "iu",
ile: "ie",
interlingue: "ie",
ina: "ia",
interlingua: "ia",
ind: "id",
indonesian: "id",
ipk: "ik",
inupiaq: "ik",
isl: "is",
icelandic: "is",
ita: "it",
italian: "it",
jav: "jv",
javanese: "jv",
jpn: "ja",
japanese: "ja",
kal: "kl",
kalaallisut: "kl",
kan: "kn",
kannada: "kn",
kas: "ks",
kashmiri: "ks",
kat: "ka",
georgian: "ka",
kau: "kr",
kanuri: "kr",
kaz: "kk",
kazakh: "kk",
khm: "km",
centralkhmer: "km",
kik: "ki",
kikuyu: "ki",
kin: "rw",
kinyarwanda: "rw",
kir: "ky",
kirghiz: "ky",
kom: "kv",
komi: "kv",
kon: "kg",
kongo: "kg",
kor: "ko",
korean: "ko",
ksh: "gmw-cfr",
kua: "kj",
kuanyama: "kj",
kv: "kpv",
lao: "lo",
lat: "la",
latin: "la",
lav: "lv",
latvian: "lv",
lim: "li",
limburgan: "li",
lin: "ln",
lingala: "ln",
lit: "lt",
lithuanian: "lt",
ltz: "lb",
luxembourgish: "lb",
lub: "lu",
lubakatanga: "lu",
lug: "lg",
ganda: "lg",
mah: "mh",
marshallese: "mh",
mal: "ml",
malayalam: "ml",
mar: "mr",
marathi: "mr",
chm: "mhr",
mari: "mhr",
mkd: "mk",
macedonian: "mk",
mlg: "mg",
malagasy: "mg",
mlt: "mt",
maltese: "mt",
mon: "mn",
mongolian: "mn",
mri: "mi",
maori: "mi",
msa: "ms",
malay: "ms",
mya: "my",
burmese: "my",
nau: "na",
nauru: "na",
hokkien: "nan-hbl",
hokkienese: "nan-hbl",
fujian: "nan-hbl",
fujianese: "nan-hbl",
hainam: "hnm",
hainan: "hnm",
hainanese: "hnm",
leizhou: "luh",
"zhx-lui": "luh",
teochew: "nan-tws",
teochewese: "nan-tws",
"zhx-teo": "nan-tws",
wep: "nds-de",
westphalian: "nds-de",
germanlowgerman: "nds-de",
dutchlowsaxon: "nds-nl",
act: "nds-nl",
achterhoeks: "nds-nl",
drt: "nds-nl",
drents: "nds-nl",
gos: "nds-nl",
gronings: "nds-nl",
sdz: "nds-nl",
sallands: "nds-nl",
stl: "nds-nl",
stellingwerfs: "nds-nl",
twd: "nds-nl",
twents: "nds-nl",
vel: "nds-nl",
veluws: "nds-nl",
nav: "nv",
navajo: "nv",
nbl: "nr",
southndebele: "nr",
nde: "nd",
northndebele: "nd",
ndo: "ng",
ndonga: "ng",
nep: "ne",
nepali: "ne",
nld: "nl",
dutch: "nl",
flemish: "nl",
nno: "nn",
norwegiannynorsk: "nn",
nob: "nb",
norwegianbokmal: "nb",
nor: "no",
norwegian: "no",
nya: "ny",
nyanja: "ny",
oci: "oc",
occitan: "oc",
oji: "oj",
ojibwa: "oj",
ori: "or",
oriya: "or",
orm: "om",
oromo: "om",
oss: "os",
ossetian: "os",
pan: "pa",
panjabi: "pa",
pfl: "gmw-rfr",
pli: "pi",
pali: "pi",
pol: "pl",
polish: "pl",
por: "pt",
portuguese: "pt",
pus: "ps",
pushto: "ps",
que: "qu",
quechua: "qu",
roh: "rm",
romansh: "rm",
ron: "ro",
romanian: "ro",
rn: "rw",
run: "rw",
rundi: "rw",
rus: "ru",
russian: "ru",
sag: "sg",
sango: "sg",
san: "sa",
sanskrit: "sa",
sin: "si",
sinhala: "si",
slk: "sk",
slovak: "sk",
slv: "sl",
slovenian: "sl",
sme: "se",
northernsami: "se",
smo: "sm",
samoan: "sm",
sna: "sn",
shona: "sn",
snd: "sd",
sindhi: "sd",
som: "so",
somali: "so",
sot: "st",
southernsotho: "st",
spa: "es",
spanish: "es",
sqi: "sq",
albanian: "sq",
srd: "sc",
sardinian: "sc",
sr: "sh",
srp: "sh",
serbian: "sh",
ssw: "ss",
swati: "ss",
sun: "su",
sundanese: "su",
swa: "sw",
swahili: "sw",
swe: "sv",
swedish: "sv",
tah: "ty",
tahitian: "ty",
tam: "ta",
tamil: "ta",
tat: "tt",
tatar: "tt",
tel: "te",
telugu: "te",
tgk: "tg",
taishanese: "zhx-tai",
tajik: "tg",
tgl: "tl",
tagalog: "tl",
tha: "th",
thai: "th",
tir: "ti",
tigrinya: "ti",
ton: "to",
tonga: "to",
tsn: "tn",
tswana: "tn",
tso: "ts",
tsonga: "ts",
tuk: "tk",
turkmen: "tk",
tur: "tr",
turkish: "tr",
twi: "tw",
uig: "ug",
uighur: "ug",
ukr: "uk",
ukrainian: "uk",
urd: "ur",
urdu: "ur",
uzb: "uz",
uzbek: "uz",
ven: "ve",
venda: "ve",
vie: "vi",
vietnamese: "vi",
westflemish: "vls",
vol: "vo",
volapuk: "vo",
wln: "wa",
walloon: "wa",
wol: "wo",
wolof: "wo",
xho: "xh",
xhosa: "xh",
yid: "yi",
yiddish: "yi",
yor: "yo",
yoruba: "yo",
zbc: "lod",
zbe: "lod",
zbw: "lod",
zha: "za",
zhuang: "za",
zh: "cmn",
zho: "cmn",
chinese: "cmn",
zul: "zu",
zulu: "zu",
};
// }}}
// FIXME: merge into above
var c = 'Çînî';
var a = 'Erebî';
var nesting = {
aae: 'Albanî/Arbëreş',
aat: 'Albanî/Arvanitika',
als: 'Albanî/Tosk',
aln: 'Albanî/Gheg',
apj: 'Apaçî',
apm: 'Apaçî',
apw: 'Apaçî',
//Bai
bca: 'Bayî/Bayiya navendî',
bfc: 'Bayî/Bayiya bakurî',
bfs: 'Bayî/Bayiya başûrî',
lay: 'Bayî/Lama baiyî',
//Eastern Cham (cjm) and Western Cham (cja) to be nested under Cham (atitarev)
cjm: 'Çamî/Çamiya rojhilatî',
cja: 'Çamî/Çamiya rojavayî',
syr: 'Aramî',
syc: 'Aramî',
xcl: 'Ermenî',
axm: 'Ermenî',
// ang:'English',enm:'English', don't nest English (Encyclopetey)
//Persian nesting
prs: 'Farisî/Darî',
"fa-cls": 'Farisî/Farisiya klasîk',
"fa-ira": 'Farisî/Farisiya îranî',
fro: 'Fransî',
frm: 'Fransî',
oge: 'Gurcî',
gsw: 'Almanî',
ksh: 'Almanî',
pfl: 'Almanî',
//gmh:'German',goh:'German', don't nest OHG/MHG (-sche)
grc: 'Yûnanî/Yûnaniya kevn',
gmy: 'Yûnanî/Yûnaniya mîkenî', //el:'Greek/Modern', don't nest Modern Greek (Atelaes)
sga: 'Îrlendî',
mga: 'Îrlendî',
ckb: 'Kurdî/Soranî',
sdh: 'Kurdî/Kurdiya Başûrî',
lki: 'Kurdî/Kurdiya lekî',
//Lawa
lwl: 'Lawayî/Lawayiya rojhilatî',
lcp: 'Lawayî/Lawayiya rojavayî',
"nds-de": 'Low German',
"nds-nl": 'Low German',
nb: 'Norwêcî/Bokmål',
nn: 'Norwêcî/Nynorsk',
mhr: 'Marî/Mariya rojhilatî',
mrj: 'Marî/Mariya rojavayî',
cmg: 'Mongolî',
cst: 'Ohlonî/Ohloniya bakur',
css: 'Ohlonî/Ohloniya başûr',
//Roglai
rog: 'Roglayî/roglayiya bakurî',
rgs: 'Roglayî/roglayiya başûrî',
roc: 'Roglayî/Cacgia roglaî',
rmn: 'Romanî',
rml: 'Romanî',
rmc: 'Romanî',
rmf: 'Romanî',
rmo: 'Romanî',
rmy: 'Romanî',
rmw: 'Romanî',
dsb: 'Sorbî',
hsb: 'Sorbî',
osp: 'Spanî',
//Sama
ssb: 'Samayî/Samayiya başûrî',
sml: 'Samayî/Samayiya navendî',
sse: 'Samayî/Samayiya balangingî',
slm: 'Samayî/Pangutaran samayî',
//Sami
sma: 'Samî/samiya başûr',
sju: 'Samî/Ume samî',
sje: 'Samî/Pite samî',
smj: 'Samî/Samiya lule',
sme: 'Samî/Samiya bakurî',
sjk: 'Samî/Kemi samî',
smn: 'Samî/Samiya înarî',
sms: 'Samî/Samiya skoltî',
sia: 'Samî/Samiya akkalayî',
sjd: 'Samî/Samiya kildînî',
sjt: 'Samî/Ter samî',
tji: 'Tujiayî/Tujiayiya bakurî',
tjs: 'Tujiayî/Tujyayiya başûrî',
owl: 'Weylsî',
wlm: 'Weylsî',
"yok-bvy": 'Yokutsî',
"yok-dly": 'Yokutsî',
"yok-gsy": 'Yokutsî',
"yok-kry": 'Yokutsî',
"yok-nvy": 'Yokutsî',
"yok-ply": 'Yokutsî',
"yok-svy": 'Yokutsî',
"yok-tky": 'Yokutsî',
zh: c,
yue: c,
dng: c,
gan: c,
hak: c,
czh: c,
cjy: c,
cmn: c,
mnp: c,
cdo: c,
nan: c,
czo: c,
cpx: c,
wuu: c,
hsn: c,
lzh: c,
cnp: c,
csp: c,
ltc: c,
och: c,
wxa: c,
"nan-hbl": c,
hnm: c,
luh: c,
"nan-tws": c,
"zhx-sht": c,
"zhx-sic": c,
"zhx-tai": c,
arq: a,
aao: a,
bbz: a,
abv: a,
shu: a,
acy: a,
adf: a,
avl: a,
arz: a,
afb: a,
ayh: a,
acw: a,
ayl: a,
acm: a,
ary: a,
ars: a,
apc: a,
ayp: a,
acx: a,
aec: a,
ayn: a,
ssh: a,
ajp: a,
arb: a,
apd: a,
pga: a,
acq: a,
abh: a,
aeb: a,
auz: a
};
var stripArabicDiacritics = { strip: "\u064B\u064C\u064D\u064E\u064F\u0650\u0651\u0652" };
var stripGraveAndAcute = { strip: "\u0300\u0301" };
var fullToHalfWidthNumbers = {
from: "0123456789",
to: "0123456789"
};
// These should reflect the replacements made in [[Module:languages]], but should not necessarily be equal.
var diacriticStrippers = {
ang: {
from: "ĀāǢǣĊċĒēĠġĪīŌōŪūȲȳ",
to: "AaÆæCcEeGgIiOoUuYy",
strip: "\u0304\u0307",
}, //macron and above dot
ar: stripArabicDiacritics,
aao: stripArabicDiacritics,
acm: stripArabicDiacritics,
acx: stripArabicDiacritics,
adf: stripArabicDiacritics,
aeb: stripArabicDiacritics,
afb: stripArabicDiacritics,
ajp: stripArabicDiacritics,
apc: stripArabicDiacritics,
apd: stripArabicDiacritics,
arq: stripArabicDiacritics,
ary: stripArabicDiacritics,
arz: stripArabicDiacritics,
fa: stripArabicDiacritics,
ps: stripArabicDiacritics,
sd: stripArabicDiacritics,
ur: stripArabicDiacritics,
chl: {
from: "ÁáÉéÍíÓóÚú",
to: "AaEeIiOoUu",
strip: "\u0304",
}, //acute accent
he: {
strip: "\u05B0\u05B1\u05B2\u05B3\u05B4\u05B5\u05B6\u05B7\u05B8\u05B9\u05BA\u05BB\u05BC\u05BD\u05BF\u05C1\u05C2",
from: "-'\"",
to: "־׳״",
},
la: {
from: "ĀāĒēĪīŌōŪūȲȳ",
to: "AaEeIiOoUuYy",
strip: "\u0304",
}, //macron
lt: {
from: "áãàéẽèìýỹñóõòúù",
to: "aaaeeeiyynooouu",
strip: "\u0340\u0301\u0303",
},
nci: {
from: "ĀāĒēĪīŌōŪūȲȳ",
to: "AaEeIiOoUu",
strip: "\u0304",
}, //macron
//strip ́ and ̀ on Cyrillic Slavic languages, Serbo-Croatian has a longer list
ru: stripGraveAndAcute,
uk: stripGraveAndAcute,
be: stripGraveAndAcute,
bg: stripGraveAndAcute,
orv: stripGraveAndAcute,
cu: stripGraveAndAcute,
rue: stripGraveAndAcute,
mk: stripGraveAndAcute,
sh: {
from: "ȀȁÀàȂȃÁáĀāȄȅÈèȆȇÉéĒēȈȉÌìȊȋÍíĪīȌȍÒòȎȏÓóŌōȐȑȒȓŔŕȔȕÙùȖȗÚúŪūѝӣ",
to: "AaAaAaAaAaEeEeEeEeEeIiIiIiIiIiOoOoOoOoOoRrRrRrUuUuUuUuUuии",
strip: "\u030F\u0300\u0311\u0301\u0304",
},
sl: {
from: "áÁàÀâÂȃȂȁȀéÉèÈêÊȇȆȅȄíÍìÌîÎȋȊȉȈóÓòÒôÔȏȎȍȌŕŔȓȒȑȐúÚùÙûÛȗȖȕȔệỆộỘẹẸọỌəł",
to: "aAaAaAaAaAeEeEeEeEeEiIiIiIiIiIoOoOoOoOoOrRrRrRuUuUuUuUuUeEoOeEoOel",
strip: "\u0301\u0300\u0302\u0311\u030f\u0323",
},
kk: stripGraveAndAcute,
ky: stripGraveAndAcute,
tg: stripGraveAndAcute,
sa: {
strip: "ः",
},
/** visarga **/
bo: {
strip: "།",
},
/** shad **/
tr: {
from: "ÂâÛû",
to: "AaUu",
strip: "\u0302",
},
ja: fullToHalfWidthNumbers,
cmn: fullToHalfWidthNumbers,
yue: fullToHalfWidthNumbers,
nan: fullToHalfWidthNumbers,
ko: fullToHalfWidthNumbers,
zu: {
strip_init_hyphen: true,
}
};
function stringOrNull(val) {
return typeof val == "string" ? val : null;
}
function makeMap(obj) {
var from = stringOrNull(obj.from);
var to = stringOrNull(obj.to);
var strip = stringOrNull(obj.strip);
var map = {};
if (from && to) {
for (var i = 0; i < from.length; i++) {
map[from.charAt(i)] = to.charAt(i);
}
}
if (strip) {
for (var ii = 0; ii < strip.length; ii++) {
map[strip.charAt(ii)] = "";
}
}
return map;
}
/** letters and number 1 are used instead of palochka **/
var palochkaCorrections = {
from: "Il1",
to: "ӏӏӏ"
};
//
var arabicYa = "ي"; // Arabic letter yāʾ (U+064A ARABIC LETTER YEH)
var arabicKaf = "ك"; // Arabic letter kāf (U+0643 ARABIC LETTER KAF)
var farsiYe = "ی"; // Persian letter ye (U+06CC ARABIC LETTER FARSI YEH)
var farsiKaf = "ک"; // Persian letter kâf (U+06A9 ARABIC LETTER KEHEH)
var alifMaqsura = "ى"; // Arabic letter ʾalif maqṣūra (U+0649 ARABIC LETTER ALEF MAKSURA)
/** commonly misspelled Persian letters (Arabic instead of Persian) (to be expanded) **/
var persianCorrections = {
from: arabicKaf + arabicYa + alifMaqsura,
to: farsiKaf + farsiYe + farsiYe,
};
// These replacements will be applied when a word is submitted.
var orthographicalCorrections = {
// Replace grave accents with acute accents for translations
// into Bulgarian per Wiktionary policy
bg: {
map: { "\u0300": "\u0301", "Ѐ": "Е́", "Ѝ": "И́", "ѐ": "е́", "ѝ": "и́" },
},
abq: palochkaCorrections,
ady: palochkaCorrections,
av: palochkaCorrections,
ce: palochkaCorrections,
dar: palochkaCorrections,
inh: palochkaCorrections,
kbd: palochkaCorrections,
lbe: palochkaCorrections,
lez: palochkaCorrections,
tab: palochkaCorrections,
/** Roman to Cyrillic**/
cv: {
from: "ĂăĔĕÇçŸÿ",
to: "ӐӑӖӗҪҫӲӳ",
},
kv: {
from: "ÖöIi",
to: "ӦӧІі",
},
koi: {
from: "ÖöIi",
to: "ӦӧІі",
},
kpv: {
from: "ÖöIi",
to: "ӦӧІі",
},
os: {
from: "Ææ",
to: "Ӕӕ",
},
/* Obsolete or incorrectly used letters */
mn: {
from: "ЄєѲѳЇїVv",
to: "ӨөӨөҮүҮү",
strip: "\u0300\u0301",
},
/* cedilla to comma below */
ro: {
from: "ŞŢşţ",
to: "ȘȚșț",
},
/** ʻ is a standard symbol in Uzbek but is often replaced with ' or ` **/
uz: {
from: "'`",
to: "ʻʻ",
},
fa: persianCorrections,
"fa-ira": persianCorrections,
"fa-cls": persianCorrections,
prs: persianCorrections,
ur: persianCorrections,
/** commonly misspelled Arabic letters (Persian instead of Arabic) (to be expanded) **/
ar: {
from: farsiKaf + farsiYe,
to: arabicKaf + arabicYa,
},
ota: {
from: farsiKaf + arabicYa + alifMaqsura,
to: arabicKaf + farsiYe + farsiYe,
},
ps: {
from: arabicKaf,
to: farsiKaf,
},
/** some letters are considered more standard (to be expanded) **/
cu: {
from: "ыѹ",
to: "ꙑу",
},
/** some letters are considered more standard (to be expanded) **/
orv: {
from: "ыѹ",
to: "ꙑу",
},
/** obsolete letters **/
ab: {
from: "ҔҕҦҧ",
to: "ӶӷԤԥ",
},
};
//Returns true if a Wiktionary exists for the specified language
this.hasWiktionary = function(lang) {
if (metadata[lang] && (metadata[lang].haswikt || metadata[lang].wiktprefix))
return true;
};
//Returns the domain-name prefix of the Wiktionary for the specified language
this.getWiktionaryPrefix = function(lang) {
if (metadata[lang])
return metadata[lang].wiktprefix || (metadata[lang].haswikt && lang);
};
// Keep this in sync with ignore_caps in [[Module:translations]].
this.ignoreCaps = { "ko": true };
// Calls the callback with a boolean indicating whether the specified language
// has a Wiktionary with the specified entry. The callback might be called
// synchronously, or it might be called asynchronously.
this.hasWiktionaryWithEntry = function(lang, title, callback) {
if (this.hasWiktionary(lang)) {
if (this.ignoreCaps[lang])
title = title.replace(/^\^/, "");
// Use this when we want to give up support for Internet Explorer 11.
// URL constructor and URLSearchParams are not supported in IE11.
// var url = new URL("https://" + this.getWiktionaryPrefix(lang) + ".wiktionary.org/w/api.php");
// url.search = new URLSearchParams({
// "format": "json",
// "formatversion": "2",
// "action": "query",
// "titles": title,
// "converttitles": 1,
// "origin": "*",
// });
var url = new mw.Uri("https://" + this.getWiktionaryPrefix(lang) + ".wiktionary.org/w/api.php");
url.extend({
"format": "json",
"formatversion": "2",
"action": "query",
"titles": title,
"converttitles": 1,
"origin": "*",
});
$.ajax({
type: 'GET',
url: url.toString(),
dataType: 'json',
headers: { 'Api-User-Agent': 'EnWiktTranslationAdderGadget/0.0 (https://en.wiktionary.org/wiki/MediaWiki:Gadget-TranslationAdder.js)' },
}).done(function(data) {
var page = data && data.query && data.query.pages && data.query.pages[0];
callback(page instanceof Object ? !page.missing : false);
});
} else
callback(false);
};
//Given a language code return a default script code.
this.guessScript = function(lang) {
var scripts = (new ScriptUtils()).GetScriptsByLangCode(lang);
if (scripts && scripts.length > 0) return scripts[0];
else return false;
if (metadata[lang]) {
// enwikt language template? (ur-Arab, polytonic)
if (metadata[lang].wsc) {
return metadata[lang].wsc;
}
// ISO script code? (Arab, Grek)
if (metadata[lang].sc) {
if (typeof metadata[lang].sc == 'object')
return metadata[lang].sc[0];
else
return metadata[lang].sc;
}
}
return false;
};
// In a given language, would we expect a translation of the title to have the capitalisation
// of word?
this.expectedCase = function(lang, title, word) {
if (metadata[lang] && metadata[lang].allowCaps)
return true;
if (title.substr(0, 1).toLowerCase() != title.substr(0, 1))
return true;
return word.substr(0, 1).toLowerCase() == word.substr(0, 1);
};
//Returns a string of standard gender letters (mfnc) or an empty string
this.getGenders = function(lang) {
if (metadata[lang])
return metadata[lang].g;
};
//Returns a string of standard noun class numbers or an empty string
this.hasNounClasses = function(lang) {
if (metadata[lang])
return metadata[lang].nclass;
};
//Returns true if the specified lang uses optional vowels or diacritics
this.needsRawPageName = function(lang) {
if (metadata[lang])
return metadata[lang].alt && !diacriticStrippers[lang];
};
function applyMap(map, str) {
var input = str.split("");
var output = "";
for (var i = 0; i < input.length; i++) {
var char = input[i];
var repl = map[char];
output += repl ? repl : char;
}
return output;
}
this.applyOrthographicalCorrections = function(lang, word) {
word = word.replace('\xAD', ''); // remove soft hyphens
var corrections = orthographicalCorrections[lang];
if (corrections) {
var map = corrections.map ? corrections.map : makeMap(corrections);
return applyMap(map, word);
}
return word;
};
// Computes the raw page name by removing diacritics (for Latin, etc.)
this.computeRawPageName = function(lang, word) {
var stripper = diacriticStrippers[lang];
if (stripper) {
var map = makeMap(stripper);
var output = applyMap(map, word);
if (stripper.strip_init_hyphen && output.length > 0 && output.charAt(0) == '-')
output = output.substr(1);
return output;
}
};
// Calls [[Module:links]]'s 'remove_diacritics' method on word and rawPageName,
// and invokes callback with two arguments: (1) the *real* raw page name
// (superseding even rawPageName), and (2) whether this real raw page name
// needs to be explicitly specified in the wikitext (i.e., whether the raw page
// name computed from rawPageName is different from the one that would have been
// computed from just word).
this.retrieveRawPageName = function(lang, word, rawPageName, callback) {
var ents = {
'<': 'lt',
'&': 'amp',
'>': 'gt'
};
var temps = {
'|': '!',
'=': '=',
'{': '(',
'}': ')'
};
function encode(s) {
s = s || '';
s = s.replace(/[|={}]/g, function(c) {
return '{{' + temps[c] + '}}';
});
s = s.replace(/[<&>]/g, function(c) {
return '&' + ents[c] + ';';
});
s = s.replace(/\t/g, ' ');
//s = encodeURIComponent(s);
return s;
}
function removeDiacritics(s) {
return '{{#invoke:languages/templates|getByCodeAllowEtym|' + lang + '|makeEntryName|' + encode(s) + '}}';
}
var text = removeDiacritics(word) + '\t' + removeDiacritics(rawPageName || word);
$.ajax({
dataType: "json",
url: '/w/api.php',
data: {
format: 'json',
action: 'expandtemplates',
prop: 'wikitext',
text: text
},
success: function(data) {
data = data && data.expandtemplates && data.expandtemplates.wikitext;
if (/<!--/.test(data)) {
data = false;
}
if (data) {
data = data && data.split('\t');
var wordMinus = data[0];
var rawPageNameMinus = data[1];
callback(rawPageNameMinus || wordMinus, rawPageNameMinus != wordMinus);
} else {
callback(rawPageName || word, rawPageName && rawPageName != word);
}
}
});
};
//Given user input, return a language code. Normalises ISO 639-1 codes and names to 639-3.
this.cleanLangCode = function(lang) {
var key = lang.toLowerCase().replace(' ', '');
if (clean[key])
return clean[key];
else
return lang;
};
// Get the nesting for a given sub-language
this.getNested = function(lang) {
if (nesting[lang])
return nesting[lang];
else
return "";
};
function temporalSortKey(langname) {
return langname.replace(/^(Ancient|Classical|Old|Middle|Early Modern|Modern) (.*)/, function(m, modifier, name) {
return ({
Ancient: 0,
Old: 1,
Middle: 2,
"Early Modern": 3,
Modern: 4
})[modifier] + name;
});
}
// For enforcing an ordering on nested languages.
this.nestsBefore = function(a, b) {
return temporalSortKey(a) < temporalSortKey(b);
};
this.getScripts = function(lang) {
var scripts = (new window.ScriptUtils()).GetScriptsByLangCode(lang) || [];
return scripts;
};
};
//</nowiki>
b2aoogw4rjs4qmfx46azszyrm1au2ph
Şablon:ng
10
1326049
6241604
6106275
2026-07-11T05:08:52Z
EmausBot
6143
Beralîkirina ducarî li ser [[Şablon:îzaha ne eleqedarî maneyê]] hat sererastkirin
6241604
wikitext
text/x-wiki
#BERALÎKIRIN [[Şablon:îzaha ne eleqedarî maneyê]]
l6abjyf7a8an8yvqgligls706k849f9
Şablon:n-g
10
1326219
6241603
6113113
2026-07-11T05:08:42Z
EmausBot
6143
Beralîkirina ducarî li ser [[Şablon:îzaha ne eleqedarî maneyê]] hat sererastkirin
6241603
wikitext
text/x-wiki
#BERALÎKIRIN [[Şablon:îzaha ne eleqedarî maneyê]]
l6abjyf7a8an8yvqgligls706k849f9
Bikarhêner:Wikihez/skrîpt/json/loader-settings.json
2
1357332
6241605
6238811
2026-07-11T08:39:04Z
Wikihez
7344
Mîhengên Loaderê hatin nûkirin (bi rêza alfabetîk)
6241605
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
6241606
6241605
2026-07-11T09:20:16Z
Wikihez
7344
Restored revision 6238811 by [[Special:Contributions/Wikihez|Wikihez]] ([[User talk:Wikihez|talk]]) ([[:m:User:Xiplus/TwinkleGlobal|TwinkleGlobal]])
6241606
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
پاشەڵ
0
1357373
6241602
6238619
2026-07-10T23:54:14Z
Wikihez
7344
/* Navdêr */
6241602
wikitext
text/x-wiki
== {{ziman|ckb}} ==
=== Navdêr ===
{{navdêr|ckb}}
# {{f|ckb|anatomî}} [[qorik]] {{îzah|hêla binî ya [[pişt|piştê]]}}
9fdg85r67kaadowykfz9gif4bpys323