Wîkîferheng kuwiktionary https://ku.wiktionary.org/wiki/Destp%C3%AAk MediaWiki 1.47.0-wmf.17 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 roj 0 3136 6347330 6337616 2026-08-31T10:21:09Z Wikihez 7344 guhartina pêşketî (DefSideBoxes); guhartina pêşketî (DefSideBoxes); guhartina pêşketî (DefSideBoxes) (bi alîkarî) 6347330 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/roːʒ/|[ro̟ːʒ]}} ** {{mj|behdînî}} {{IPA|ku|[ro̟ːʒ~ rʊːʒ]}} * {{deng|ku|LL-Q36163 (kmr)-Ebulfîda-roj.wav|Deng|dever=Bidlîs}} * {{ku-kîte}} === Navdêr === [[Wêne:Sun. - Flickr - skyseeker.jpg|thumb|Roj (1)]] {{navdêr|ku|z=m}} # {{e|ku|astronomî}} [[stêr|Stêra]] ku dinya li dorê [[zivirîn|dizivire]] û [[ronahî|ronahiyê]] û [[germahî|germahiyê]] dide. #: {{hevmane|ku|tav|hetav|xor|şems}} #: {{mk|ku|'''Roj''' ji rojhilatê hiltê û li rojavayê ava dibe.}} #* {{bêmînak|ku}} # [[tav|Tava]] ku ev [[stêr]] dide. #* {{bêmînak|ku}} # Ji [[spêde]]yê heta [[êvar]]ê, [[dem]]a ku [[dinya]] [[ron]], ne [[tarî]], ne [[şev]]. #: {{mk|ku|Mirov bi '''roj''' kar dikin û bi şev [[nivistin|dinivin]].}} #* {{bêmînak|ku}} # 24 [[saet]], [[şevûroj]] #: {{mk|ku|Di mehekê de 30 yan 31 '''roj''' hene lê di meha sibatê de tenê 28 yan 29 roj hene.}} #* {{J:Robert Louis Stevenson:Meseleya Seyr a Dr. Jekyll û Mr. Hyde|r=43|jêgirtin='''Rojan''' da pey '''rojan;'''}} ==== Ji wêjeya klasîk ==== * {{J:Mela Hisênê Bateyî:Mewlûda Kurdî|jêgirtin='''Rojekê''' ew der sucûdê bê mefer<br />Pirr girî û hem li erşê kir nezer}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|ڕۆژ}} * {{ku-kr|рʹож}} ==== Formên alternatîv ==== {{kol3|ku | {{hw|ku|ro}} | {{hw|ku|rok}} | {{hw|ku|rûj}} | {{hw|ku|rûs}} }} ==== Jê ==== {{kol3|ku|cure=Jê} |rojan |Rojan |rojane |rojbaş |rojbaş |rojbîn |Rojbîn |rojen |Rojen |rojeng |rojev |rojgar |Rojhat |rojî |rojîn |Rojîn |rojjimêr |roj bu roj }} ==== Têkildar ==== * {{g|ku|tava rojê}} * {{g|ku|gong}} ==== Etîmolojî ==== Ji {{ji|ine-pro|ku|*lewk-|w=[[biriqîn]], [[ronahî]] dan}} > {{ji|ira-pro||-}} ''rewç-'', têkildarî ''reoc-'' ya avestayî, ''recceh'' ya farisiya kevn, [[roc]] ya sanskrîtî, parsî, pehlewî û zazakî, ''roz'' ya farisî, ''loys'' ([[ronahî]]) ya ermenî, [[lux]] ([[ronahî]]) ya latînî, ''leukos'' (ronahî) ya yûnaniya kevn, [[Licht]] ya almanî, [[light]] (ronahî) ya îngilîzî... Hevreha [[ron]] û [[rewşen]]. * {{ji|ine-pro|ku|-}}: *'''lewk'''- ("biriqîn, ronahî dan") :* {{ji|ira-pro||-}}:*'''rewç'''- ("biriqîn") ::{{ae}}: '''reoc'''- ("biriqîn, ronahî dan"), '''raocah'''- ("ronahî") ::{{peo}}: '''recceh'''- ("roj") ::{{xpr}}: '''roc''' ("roj") ::{{pal}}: '''roc''' ("roj") ::{{sog}}: '''roc''' ("roj") ::{{fa}}: '''roz''' ("roj") ::{{bal}}: '''roç''' ("roj") ... {{ir}} ::[[kurmancî]]: '''roj''' ("roj") ::{{ckb}}: '''roj''' ("roj") ::{{zza}}: '''roc / roj''' ("roj") :{{sa}}: '''roc''' ("biriqîn, ronahî dan") :{{hy}}: '''loys ''' ("ronahî") :{{el}}: '''leukos ''' ("ronahî, spêde") :{{la}}: '''[[lux]]''' ("ronahî") :{{de}}: '''[[Licht]]''' ("ronahî") :{{en}}: '''[[light]]''' ("ronahî") ... ;{{biçûk|Çavkanî: * {{Cheung|r=316}}, * {{Horn|r=139}}, * {{Watkins|r=49}}, * {{Etymonline}} :[[hevreh|Hevreh]]: [[ron]], [[ronahî]], [[rewşen]] }} ==== Bi zaravayên din ==== * Soranî : {{W-|ckb|ڕۆژ}} {{i|bi maneya stêra ronahîder herwiha: hetaw, xor}} * Zazakî : {{W-|zza|roc}}, {{W-|zza|roj}} ==== Werger ==== {{werger-ser|tav, hetav, xor|1}} * Adîgeyî : {{W-|ady|тыгъэ}} * Afarî : {{W-|aa|ayro}} * Afrîkansî : {{W+|af|son}} * Akanî : {{W-|ak|awia}}, {{W-|ak|owia}} * Albanî : {{W|sq|diell|n}} * Almanî : {{W+|de|Sonne|m}} * Alutor : {{W-|alr|титкытит|tr=titkətit}} * Amazîxiya fasî : {{W-|zgh|ⵜⴰⴼⵓⴽⵜ}} * Amharî : {{W-|am|ጸሓይ}}, {{W-|am|ፀሐይ}} * Apaçî: *: Apaçiya rojava : {{W-|apw|ya'áí}} * Aramî : *: Aramiya nû ya asûrî : {{W-|aii|ܫܡܫܐ|m|tr=šimšā}} *: Siryaniya klasîk : {{W-|syc|ܫܡܫܐ|g|tr=šemšā}} * Asamî : {{W-|as|সূৰ্য}} * Astûrî : {{W-|ast|sol|n}} * Avarî : {{W-|av|бакъ}} * Azerî : {{W+|az|günəş}} * Badagayî : {{W-|bfq|ಸೂರಿಯ}}, {{W-|bfq|ಚೂರಿಯನ್}} * Bahnarî : {{W-|bdq|'năr}} * Balînî : {{W-|ban|matanai}} * Bambarayî : {{W-|bm|tile}} * Baskî : {{W-|eu|iguzki}}, {{W-|eu|eguzki}} * Başkîrî : {{W-|ba|ҡояш}} * Belarusî : {{W-|be|со́нца|nt}} * Belûçî : {{W-|bal|روچ|tr=roc}} * Bengalî : {{W-|bn|সূর্য}}, {{W-|bn|আফতাব|tr=aphtab}} * Bîkoliya naverast : {{W-|bcl|saldang}}, {{W-|bcl|aldaw}} * Bulgarî : {{W-|bg|слъ́нце|nt}} * Burmayî : {{W-|my|နေ}} * Buryatî : {{W-|bua|наран}} * Chamicuroyî : {{W-|ccc|mo'sojko}} * Conxayî : {{W-|dz|ཉི་མ་}} * Çekî : {{W+|cs|slunce|nt}} * Çîçewayî : {{W-|ny|dzuwa}} * Çîkasawî : {{W-|cic|hashi'}} * Çînî : *: Kantonî : {{W-|yue|太陽|tr=taai3 joeng4}}, {{W-|yue|日頭|tr=jat6 tau2}}, {{W-|yue|熱頭|tr=jit6 tau2}} *: Dunganî : {{W-|dng|эрту}}, {{W-|dng|жәту}} *: Hakkayî : {{W-|hak|日頭|tr=ngit-thèu}}, {{W-|hak|太陽|tr=thai-yòng}} *: Mandarînî : {{W+|cmn|太陽|tr=tàiyáng}}, {{W+|cmn|日|tr=rì}}, {{W+|cmn|日頭|tr=rìtou, rìtóu}}, {{W-|cmn|恆星|tr=héngxīng}} *: Minnanî : {{W-|nan|日頭|tr=[[ji̍t-thâu]], [[li̍t-thâu]]}}, {{W-|nan|太陽|tr=[[thài-iâng]]}} *: Wuyî : {{W-|wuu|太陽|tr=tha hhian}}, {{W-|wuu|日頭|tr=nyiq deu}} * Çuvaşî : {{W-|cv|хӗвел}} * Danmarkî : {{W+|da|sol}} * Divehî : {{W-|dv|އިރު}} * Dongxiang : {{W-|sce|naran}} * Eastern Cham : {{W-|cjm|ꨀꨕꨪꨓꨳꩀ}}, {{W-|cjm|ꨀꨳꨩ ꨨꨣꨬ}} * Erebî : {{W-|ar|شَمْس|m}} *: Erebiya misrî : {{W-|arz|شمس|m|tr=šams}} *: Erebiya kendavî : {{W-|afb|شمس|tr=ʃəms}} *: Erebiya hîcazî : {{W-|acw|شَمْس|m|tr=šams}} *: Erebiya fasî : {{W-|ary|شمش|m|tr=šamš}}, {{W-|ary|شمس|tr=šams}} * Ermenî : {{W+|hy|արև}} * Esperantoyî : {{W-|eo|suno}} * Estonî : {{W-|et|päike}} * Etiyopiya klasîk : {{W-|gez|ፀሐይ}} * Evenkî : {{W-|evn|дылача}} * Farisî : {{W-|fa|خورشید|tr=xoršid}}, {{W-|fa|خور|tr=xor}}, {{W-|fa|شمس|tr=šams}} * Fataluku : {{W-|ddg|vacu}} * Fenîkî : {{W-|phn|𐤔𐤌𐤔|ts=šamš}} * Ferî : {{W+|fo|sól|m}} * Fîjî : {{W-|fj|siga}}, {{W-|fj|mata ni siga}} * Fînî : {{W-|fi|aurinko}} * Fransî : {{W-|fr|soleil|n}} * Frîsî : {{W-|fy|sinne|g}} * Gaelîka skotî : {{W-|gd|grian|m}} * Galîsî : {{W-|gl|sol|n}} * Gujaratî : {{W-|gu|સૂર્ય}} * Gurcî : {{W-|ka|მზე}} * Gurindji : {{W-|gue|gangirriny}}, {{W-|gue|wulngarn}} * Guwaranî : {{W-|gn|kuarahy}} * Haîtî : {{W-|ht|solèy}} * Hawayî : {{W-|haw|lā}} * Hawsayî : {{W+|ha|rana}} * Higaonon : {{W-|mba|anlaw}} * Hindî : {{W-|hi|सूरज|n}}, {{W-|hi|ख़्वुरशेद|n}}, {{W-|hi|रवि|n}}, {{W-|hi|सूर्य|n}}, {{W-|hi|खुरशीद|n}}, {{W-|hi|शम्स|n}}, {{W-|hi|आफ़ताब|n}} * Hîlîgaynonî : {{W-|hil|adlaw}} * Hmongî : {{W-|mww|hnub}}, {{W-|mww|lub hnub}} * Holendî : {{W+|nl|zon|m}} * Indonezî : {{W+|id|matahari}}, {{W+|id|surya}} * Inglîziya kevn : {{W-|ang|sunne|m}} * Inglîziya navîn : {{W-|enm|sonne}}, {{W-|enm|sunne}} * Îngilîzî : {{W+|en|sun}} * Iştihardî : {{W-|esh|افدب|cuda=اَفدِب|tr=afdeb}} * Iu Mien : {{W-|ium|mba'hnoi}} * Îbranî : {{W-|he|שֶׁמֶשׁ|n|m|tr=shémesh}}, {{W-|he|כּוֹכָב|n|tr=kokháv}} * Îdoyî : {{W+|io|suno}} * Înuîtî : {{W+|iu|ᓯᕿᓂᖅ}} * Înupîakî : {{W-|ik|siqiñiq}} * Îrlendî : {{W-|ga|grian|m}} * Îtalî : {{W+|it|sole|n}} * Îzlendî : {{W+|is|sól|m}}, {{W+|is|sólstjarna|m}}, {{W+|is|fastastjarna|m}} * Japonî : {{W+|ja|太陽|tr=taiyō}}, {{W+|ja|恒星|tr=kōsei}}, {{W+|ja|日|tr=ひ, hi}} * K'iche' : {{W-|quc|q'ij}} * Kalalîsûtî : {{W-|kl|seqineq}} * Kalmîkî : {{W-|xal|нарн}} * Kamasau : {{W-|kms|nginy}} * Kambaata : {{W-|ktb|arruchcho}} * Kannadayî : {{W+|kn|ಸೂರ್ಯ}} * Kapverdî : {{W-|kea|sol}} * Kaqchikel : {{W-|cak|ik}} * Kaşûbî : {{W-|csb|słuńce|nt}} * Katalanî : {{W-|ca|sol|n}} * Keçwayî : {{W-|qu|inti}} * Khasi : {{W-|kha|sngi}} * Kirgizî : {{W+|ky|күн}} * Kitembo : {{W-|tbt|esuba}} * Kîkûyûyî : {{W-|ki|riũa}} * Kîngalî : {{W+|si|ඉර}} * Kînyarwandayî : {{W-|rw|izuba}} * Koreyî : {{W+|ko|해}}, {{W-|ko|태양(太陽)}} * Kornî : {{W-|kw|howl|n}} * Kreyoliya morîtanî : {{W-|mfe|soley}} * Kreyoliya seyşelê : {{W-|crs|soley}} * Kumikî : {{W-|kum|гюнеш}} * Lamboyayî : {{W-|lmy|lado}} * Latgalî : {{W-|ltg|saule}} * Latînî : {{W+|la|sōl|n}} * Latviyayî : {{W+|lv|saule|m}} * Lawsî : {{W+|lo|ຕາເວັນ}} * Lazî : {{W-|lzz|მჟურა}} * Lezgînî : {{W-|lez|рагъ}} * Lîtwanî : {{W+|lt|saulė|m}} * Lîvonî : {{W-|liv|pǟva}}, {{W-|liv|pǟvaļikki}} * Lueyî : {{W-|khb|ᦎᦱᦞᧃ}} * Luksembûrgî : {{W+|lb|Sonn|m}} * Makasae : {{W-|mkz|watu}} * Makedonî : {{W-|mk|со́нце|nt}} * Malagasî : {{W+|mg|masoandro}} * Malayalamî : {{W+|ml|സൂര്യൻ}} * Malezî : {{W+|ms|matahari}} * Maltayî : {{W+|mt|xemx|m}} * Mançûyî : {{W-|mnc|ᡧᡠᠨ}} * Mansaka : {{W-|msk|suga}} * Maorî : {{W+|mi|rā}} * Maranaoyî : {{W-|mrw|alongan}}, {{W-|mrw|senang}} * Maratî : {{W-|mr|सूर्य}} * Marşalî : {{W-|mh|aļ}} * Mayayiya yukatekî : {{W-|yua|k'iin}} * Mecarî : {{W+|hu|Nap}} * Megrelî : {{W-|xmf|ბჟა}} * Mezquital Otomi : {{W-|ote|hyadi}} * Mongolî : {{W+|mn|нар}} * Mwani : {{W-|wmw|juwa}} * Nahuatl: *: Nahuatliya navendî : {{W-|nhn|tonatih}} *: Klasîk: {{W-|nci|tonatiuh}} * Nanayî : {{W-|gld|сиун}} * Napolîtanî : {{W-|nap|sole|n}} * Navajoyî : {{W-|nv|jóhonaaʼéí}} * Nedersaksî : {{W+|nds|Sünn|m}} * Nepalî : {{W-|ne|सूर्य}} * Nganasanî : {{W-|nio|коу|tr=kou}} * Nivkh : {{W-|niv|кʼеӈ}} * Norwecî : {{W+|no|sol}} * O'odhamî : {{W-|ood|taṣ}} * Ohloniya bakur : {{W-|cst|hismen}}, {{W-|cst|hísmén}} * Ojibweyî : {{W-|oj|giizis}} * Oksîtanî : {{W+|oc|solelh|n}} * Oriyayî : {{W-|or|ସୂର୍ଯ୍ୟ}} * Oromoyî : {{W-|om|biiftuu}} * Osetî : {{W-|os|хур}} * Oygurî : {{W+|ug|كۈن}}, {{W+|ug|قۇياش}} * Ozbekî : {{W+|uz|quyosh}}, {{W+|uz|oftob}} * Pa'o karen : {{W-|blk|မွူး}} * Palî : {{W-|pi|suriya|n}} * Papyamentoyî : {{W-|pap|solo}} * Pelayî : {{W-|bxd|pui⁵⁵}} * Peştûyî : {{W+|ps|لمر|n|tr=lmar}} * Piedmontîsî : {{W-|pms|sol|n}} * Plodîşî : {{W-|pdt|Sonn|m}} * Polonî : {{W+|pl|słońce|nt}} * Portugalî : {{W+|pt|sol|n}} * Puncabî : {{W+|pa|ਸੂਰਜ}} * Qazaxî : {{W+|kk|күн}} * Qiptî : {{W-|cop|ⲣⲏ}}, {{W-|cop|ϧⲏⲓ}} * Romagnolî : {{W-|rgn|sôl|n}} * Romanî : {{W-|rom|kham}} * Romanyayî : {{W+|ro|soare|n}} * Rusî : {{W-|ru|со́лнце|nt}} * Rusînî : {{W-|rue|со́нце|nt}} * S'gaw karenî : {{W-|ksw|မုၢ်}} * Saho : {{W-|ssy|ayro}} * Samoayî : {{W-|sm|la}} * Sanskrîtî : {{W+|sa|सूर्य|n}}, {{W+|sa|सूर|n}} * Sebwanoyî : {{W-|ceb|adlaw}} * Semai : {{W-|sea|mat jiis}} * Sicîlî : {{W+|scn|suli|n}} * Sidamo : {{W-|sid|arrisho}} * Silesî : {{W-|szl|słůńce|nt}} * Sirananî : {{W-|srn|son}} * Sirboxirwatî : *: Kirîlî: {{W-|sh|сунце|nt}} *: Latînî: {{W+|sh|sunce|nt}} * Slaviya kevn : *: Kirîlî: {{W-|cu|слъньцє|nt}} * Slaviya rojavayî ya kevn : {{W-|orv|сълньце|nt}} * Slovakî : {{W+|sk|slnko|nt}} * Slovenî : {{W+|sl|sónce|nt}} * Sorbî: *: Sorbiya jêrîn : {{W-|dsb|słyńco|nt}} *: Sorbiya jorîn : {{W-|hsb|słónco|nt}} * Sotoyiya başûr : {{W+|st|letsatsi}} * Spanî : {{W-|es|sol|n}} * Sundanî : {{W-|su|ᮕᮔᮧᮔ᮪ᮕᮧᮆ}} * Svanî : {{W-|sva|ბჟა}} * Swahîlî : {{W+|sw|jua}} * Swêdî : {{W+|sv|sol|g}} * Şanî : {{W-|shn|ဝၼ်း}} * Tày : {{W-|tyz|tha vằn}} * Tacikî : {{W+|tg|хуршед}}, {{W+|tg|офтоб}} * Tagabawayî : {{W-|bgs|álló}} * Tagalogî : {{W+|tl|araw}} * Tamîlî : {{W+|ta|சூரியன்}} * Tarantino : {{W-|roa-tar|sule|n}} * Tarifit : {{W-|rif|tfušt|m}}, {{W-|rif|tfuyt|m}} * Tausug : {{W-|tsg|suga}} * Tayî : {{W+|th|ดวงอาทิตย์}}, {{W+|th|ตะวัน}}, {{W+|th|ดาวฤกษ์|tr=daao-rə̂ək}} * Telûgûyî : {{W+|te|సూర్యుడు}} * Teterî : {{W+|tt|кояш}} * Tetûmî : {{W-|tet|loro}} * Tirkî : {{W+|tr|güneş}} * Tirkmenî : {{W-|tk|gün}} * Tiwi : {{W-|tiw|yiminga}}, {{W-|tiw|warnarringa}}, {{W-|tiw|pukwiyi}} * Tîbetî : {{W-|bo|ཉི་མ}} * Tongî : {{W-|to|la'ā}} * Toxarî A : {{W-|xto|koṃ}} * Toxarî B : {{W-|txb|kauṃ}} * Tumbukayî : {{W-|tum|zuwa}} * Tuvanî : {{W-|tyv|хүн}} * Urdûyî : {{W+|ur|سورج|n|tr=sūraj}}, {{W-|ur|خورشید|n|tr=khurśed}}, {{W-|ur|روی|n|tr=ravi}}, {{W-|ur|سوریہ|n|tr=sūrya}} * Ûkraynî : {{W-|uk|со́нце|nt}} * Viyetnamî : {{W+|vi|mặt trời}} * Walonî : {{W+|wa|solea|n}}, {{W+|wa|solo|n}} * Warlpiri : {{W-|wbp|wanta}}, {{W-|wbp|yurrupupu}}, {{W-|wbp|ngirlilypa}} * Wîlamowî : {{W-|wym|zun}} * Ximêrî : {{W+|km|អាទិត្យ}}, {{W+|km|សុរិយ}}, {{W+|km|ថ្ងៃ}} * Yagnobî : {{W-|yai|офтоб}}, {{W-|yai|хур}} * Yakutî : {{W-|sah|күн}} * Yidîşî : {{W-|yi|זון|m}} * Yiyiya siçuwayî : {{W-|ii|ꉘꁮ}} * Yupîkiya navendî : {{W-|esu|akerta}}, {{W-|esu|macaq}}, {{W-|esu|puqlaneq}} * Yûnanî : {{W-|el|ήλιος|n}} *: Kevn: {{W-|grc|ἥλιος|n}} * Zhuangî : {{W-|za|daengngoenz}}, {{W-|za|gyangjngoenz}} * Zuluyî : {{W+|zu|ilanga}} {{werger-bin}} {{werger-ser|24 saet; sibê heta êvarê}} * Abxazî : {{W-|ab|амш}} * Adîgeyî : {{W-|ady|мафэ}} * Afarî : {{W-|aa|ayró|m}} * Afrîkansî : {{W+|af|dag}} * Aghwan : {{W-|xag|𐕘𐔼}} * Ahomî : {{W-|aho|𑜈𑜃𑜫}} * Akanî : {{W-|ak|ɛda}} * Aklanon : {{W-|akl|adlaw}} * Albanî : {{W+|sq|ditë|m}} * Almaniya Pennsylvania : {{W-|pdc|Daag}} * Almanî : {{W+|de|Tag|n}} *: Almaniya navendî ya rojhilat : {{W-|gmw-ecg|Tag|n}} * Amharî : {{W-|am|ቀን}}, {{W-|am|መአልት}} * Andî : {{W-|ani|зубу}} * Aragonî : {{W+|an|diya|n}}, {{W+|an|día|n}} * Aramî : *: Aramiya nû ya asûrî : {{W-|aii|ܝܵܘܡܵܐ|n|tr=yawma}} *: Siryaniya klasîk : {{W-|syc|ܝܘܡܐ|n|tr=yawmā}} *: Aramiya babîlonî ya cihûyî: {{W-|arc|יוֹמָא|n|tr=yômā}} * Arçî : {{W-|aqc|ихъ}} * Aromanî : {{W-|rup|dzuã|m}}, {{W-|rup|dzãuã|m}}, {{W-|rup|dzã|m}} * Arrernteyiya rojavayî : {{W-|aer|arlte}} * Asamî : {{W-|as|দিন}} * Astûrî : {{W-|ast|día|n}} * Atayalî : {{W-|tay|bingqi'}} * Avarî : {{W-|av|къо}} * Avestayî : {{W-|ae|𐬭𐬀𐬊𐬗𐬀𐬵}}, {{W-|ae|𐬀𐬌𐬌𐬀𐬭}} * Aynuyî : {{W-|ain|トホ|tr=toho}} * Azerî : {{W+|az|gün}}, {{W-|az|sutka}} * Balînî : {{W-|ban|dina}} * Baskî : {{W-|eu|egun}} * Başkîrî : {{W-|ba|тәүлек}}, {{W-|ba|көн}} * Baureyî : {{W-|brg|roseskoner}} * Belarusî : {{W-|be|су́ткі|p}}, {{W-|be|дзень|n}}, {{W-|be|до́ба|m}}, {{W-|be|со́дні|p}} * Belûçî : {{W-|bal|روچ|tr=roc}} * Bengalî : {{W-|bn|দিন}} * Bextiyarî : {{W-|bqi|روز|tr=ruz}} * Bîkoliya naverast : {{W-|bcl|aldaw}} * Bojpûrî : {{W-|bho|𑂠𑂱𑂢}} * Bretonî : {{W+|br|deiz|n}}, {{W+|br|devezh|n}} * Buduxî : {{W-|bdk|йыгъ}} * Bugî : {{W-|bug|esso}} * Bulgarî : {{W-|bg|деноно́щие|nt}}, {{W-|bg|ден|n}} * Burmayî : {{W+|my|နေ့}} * Buryatî : {{W-|bua|үдэр}} * Central Melanau : {{W-|mel|lau}} * Chamicuroyî : {{W-|ccc|senesyako}} * Çeçenî : {{W-|ce|де}} * Çekî : {{W+|cs|den|n}} * Çerokî : {{W-|chr|ᎢᎦ}} * Çîçewayî : {{W-|ny|tsiku}} * Çînî : *: Kantonî : {{W-|yue|日|tr=jat6}} *: Dunganî : {{W-|dng|тян}}, {{W-|dng|йитян}} *: Hakkayî : {{W-|hak|日|tr=ngit}} *: Mandarînî : {{W+|cmn|天|tr=tiān}}, {{W+|cmn|日|tr=rì}} *: Min dongî : {{W-|cdo|日|tr=nĭk}} *: Minnanî : {{W-|nan|日|tr=ji̍t, li̍t}}, {{W-|nan|工|tr=kang}} *: Wuyî : {{W-|wuu|天}}, {{W-|wuu|日}} * Çuvaşî : {{W-|cv|кун}} * Çûkî : {{W-|chk|ran}} * Danmarkî : {{W+|da|døgn|nt}}, {{W+|da|dag|g}} * Daur : {{W-|dta|udure}} * Divehî : {{W-|dv|ދުވަސް}} * Dolganî : {{W-|dlg|күн}} * Dongxiang : {{W-|sce|udu}} * Drung : {{W-|duu|ni}} * Dusuniya navendî : {{W-|dtp|tadau}} * Eastern Bontoc : {{W-|ebk|ka-orkawan}} * Erebî : {{W-|ar|يَوْم|n}} *: Erebiya misrî : {{W-|arz|يوم|n|tr=yōm}}, {{W-|arz|ايام|m-p|tr=eyām}} *: Erebiya kendavî : {{W-|afb|يوم|tr=yom}} *: Erebiya hîcazî : {{W-|acw|يوم|n|tr=yōm}} *: Erebiya fasî : {{W-|ary|يوم|n|tr=yūm}} * Ermenî : {{W+|hy|օր}} * Esperantoyî : {{W-|eo|tago}} * Estonî : {{W-|et|ööpäev}}, {{W-|et|päev}} * Evenî : {{W-|eve|инэӈ}} * Evenkî : {{W-|evn|тыргани}} * Eweyî : {{W-|ee|ŋkeke|nt}} * Farisî : {{W-|fa|روز|tr=ruz}} * Fenîkî : {{W-|phn|𐤉𐤌}} * Ferî : {{W+|fo|dagur|n}}, {{W-|fo|samdøgur|nt}} * Fîjî : {{W+|fj|siga}} * Fînî : {{W+|fi|päivä}}, {{W+|fi|vuorokausi}} * Fransiya kevn : {{W-|fro|jur}} * Fransî : {{W+|fr|jour|n}}, {{W+|fr|journée|m}} *: Fransiya kevn : {{W-|fro|jor}} * Frîsî: *: Frîsiya bakur : {{W-|frr|dai|n}}, {{W-|frr|däi|n}} *: Prusîya kevn : {{W-|prg|di}}, {{W-|ofs|dei|n}} *: Frîsî : {{W+|fy|dei|g}} * Friyolî : {{W-|fur|dì}}, {{W-|fur|zornade|m}} * Gaelîka skotî : {{W-|gd|latha|n}} * Galîsî : {{W-|gl|día|n}} * Gotî : {{W-|got|𐌳𐌰𐌲𐍃|n}} * Gujaratî : {{W-|gu|દિવસ}} * Gurcî : {{W+|ka|დღე}}, {{W-|ka|დღე-ღამე}}, {{W-|ka|დღე და ღამე}} * Hawayî : {{W-|haw|lā}}, {{W-|haw|ao}} * Hawsayî : {{W+|ha|rana}} * Higaonon : {{W-|mba|anlaw}} * Hindî : {{W-|hi|दिन|n}}, {{W-|hi|वार|n}}, {{W-|hi|दिवस|n}}, {{W-|hi|रोज़|n}}, {{W-|hi|यौम|n}}, {{W-|hi|रोज|n}}, {{W-|hi|दिहाड़ा|n}} * Hmongî : {{W-|mww|hnub}} * Holendî : {{W+|nl|dag|n}}, {{W+|nl|etmaal|nt}} * Hunsrikî : {{W-|hrx|Daagh|n}}, {{W-|hrx|taach|n}} * Iban : {{W-|iba|hari}} * Indonezî : {{W+|id|hari}} * Inglîziya kevn : {{W-|ang|dæġ}} * Inglîziya navîn : {{W-|enm|day}} * Îngilîzî : {{W+|en|day}} * Isnag : {{W-|isd|alxaw}} * Îbranî : {{W-|he|יְמָמָה|m|tr=yemama}}, {{W-|he|יוֹם|n|tr=yom}} * Îdoyî : {{W+|io|dio}} * Îlokanoyî : {{W-|ilo|aldaw}} * Îngûşî : {{W-|inh|ди}} * Înterlîngua : {{W+|ia|die}} * Îrlendî : {{W+|ga|lá|n}} * Îstriyotî : {{W-|ist|dèi}}, {{W-|ist|zurnada|m}} * Îtalî : {{W+|it|giorno|n}} * Îzlendî : {{W+|is|dagur|n}} * Japonî : {{W+|ja|日|tr=ひ, hi}}, {{W+|ja|一日|tr=いちにち, ichinichi}} * Javayiya kevn : {{W-|kaw|dina}} * Javayî : {{W+|jv|ꦢꦶꦤ}}, {{W+|jv|ꦢꦶꦤ꧀ꦠꦼꦤ꧀}} * Jurchen : {{W-|juc|inengi}} * Kalalîsûtî : {{W+|kl|ulloq}} * Kalmîkî : {{W-|xal|өдр}} * Kambaata : {{W-|ktb|bara}} * Kannadayî : {{W+|kn|ದಿನ}} * Kaşûbî : {{W-|csb|dzéń|n}} * Katalanî : {{W+|ca|dia|n}}, {{W+|ca|jorn|n}} * Kayingangî : {{W-|kgp|kurã}} * Keçwayî : {{W+|qu|p'unchaw}}, {{W-|qu|puncau}}, {{W-|qu|hunag}} * Keşmîrî : {{W+|ks|دۄہ}}, {{W+|ks|دۆہ}}, {{W+|ks|روز}} * Kipçakî : {{W-|qwm|کون|tr=kün}} * Kirgizî : {{W+|ky|күн}} * Kîngalî : {{W+|si|දවස}} * Koreyî : {{W-|ko|일주야(一晝夜)}}, {{W+|ko|하루}}, {{W+|ko|일}} * Kornî : {{W-|kw|dydh|n}} * Krî : {{W-|cr|ᑮᓯᑳᐤ}} * Kven : {{W-|fkv|janturi}}, {{W-|fkv|vuorokausi}} * Ladînî : {{W-|lld|dì}} * Lakî : {{W-|lbe|кьини}} * Lakotayî : {{W-|lkt|aŋpétu}} * Lamboyayî : {{W-|lmy|lado}} * Latgalî : {{W-|ltg|dīna|m}} * Latînî : {{W+|la|diēs|n|m}}, {{W+|la|lūx|m}} * Latviyayî : {{W+|lv|diena|m}}, {{W-|lv|diennakts}} * Lawsî : {{W-|lo|ວັນ}} * Lazî : {{W-|lzz|დღა}} * Lezgînî : {{W-|lez|йугъ}}, {{W-|lez|югъ}} * Lîgûrî : {{W-|lij|giorno}} * Lîmbûrgî : {{W+|li|daag}} * Lîtwanî : {{W+|lt|para}}, {{W+|lt|diena|m}} * Lîvonî : {{W-|liv|pǟva}} * Lombardî : {{W-|lmo|dì}} * Lubuagan Kalinga : {{W-|knb|egew}} * Lueyî : {{W-|khb|ᦞᧃ}} * Luksembûrgî : {{W+|lb|Dag}} * Mòçenoyî : {{W-|mhn|ta|n}} * Magahi : {{W-|mag|𑂠𑂱𑂢𑂰|tr=dinā}} * Maguindanao : {{W-|mdh|gay}} * Maithili : {{W-|mai|दिन}} * Makasarî : {{W-|mak|allo}} * Makedonî : {{W+|mk|ден|n}} * Malayalamî : {{W+|ml|ദിവസം}} * Malezî : {{W+|ms|hari}}, {{W-|ms|yaum}} * Maltayî : {{W-|mt|nhar|n}}, {{W-|mt|jum|n}} * Mançûyî : {{W-|mnc|ᡳᠨᡝᠩᡤᡳ}} * Mansaka : {{W-|msk|allaw}} * Maorî : {{W+|mi|rā}}, {{W+|mi|rangi}} * Maranaoyî : {{W-|mrw|gawi'i}} * Maratî : {{W+|mr|दिवस}} * Marîkopayî : {{W-|mrc|nyaa}} * Masayî : {{W-|mas|enkolong'|m}} * Mayayiya yukatekî : {{W-|yua|k'iin}} * Mbyá Guaraní : {{W-|gun|ára}} * Meänkiyelî : {{W-|fit|päivä}} * Mecarî : {{W+|hu|nap}} * Megrelî : {{W-|xmf|დღა}}, {{W-|xmf|ნდღა}} * Misrî : {{W-egy|sw|n|h=s-w-hrw}} * Mîrandî : {{W-|mwl|die|n}} * Mongolî : {{W+|mn|өдөр}} * Monî : {{W-|mnw|တ္ၚဲ}} * Mwani : {{W-|wmw|suku}} * Nahwatlî : {{W+|nah|tonalli}} * Nanayî : {{W-|gld|ини}} * Napolîtanî : {{W-|nap|juorno|n}} * Navajoyî : {{W-|nv|jį́}} * Nedersaksî : {{W+|nds|Dag|n}} * Nepalî : {{W+|ne|दिन}} * Nivkh : {{W-|niv|муғф}} * Normandî : {{W-|nrf|jour|n}}, {{W-|nrf|journée|m}}, {{W-|nrf|journaïe|m}} * Norsiya kevn : {{W-|non|dagr}} * Northern Thai : {{W-|nod|ᩅᩢ᩠ᨶ}} * Norwecî : {{W+|no|dag|n}}, {{W+|no|døgn|nt}} * O'odhamî : {{W-|ood|taṣ}} * Ohloniya bakur : {{W-|cst|tú̄hi}} * Oksîtaniya kevn : {{W-|pro|jorn}} * Oksîtanî : {{W+|oc|jorn|n}}, {{W+|oc|dia|n}} * Oriyayî : {{W+|or|ଦିନ}} * Osetî : {{W-|os|бон}} * Osmanî : {{W-|ota|روز|tr=rûz}}, {{W-|ota|یوم|tr=yevm}}, {{W-|ota|ایام|tr=eyyâm}}, {{W-|ota|گون|tr=gün}} * Oygurî : {{W+|ug|كۈن}} * Ozbekî : {{W+|uz|kun}} * Palî : {{W-|pi|dina}} * Papyamentoyî : {{W-|pap|día}} * Pehlewî : {{W-|pal|𐭩𐭥𐭬|ts=rōz}} * Peştûyî : {{W+|ps|ورځ|m|tr=wraj}}, {{W+|ps|روځ|m|tr=rwaj}} * Plodîşî : {{W-|pdt|Dach|n}} * Polabî : {{W-|pox|dan|n}} * Polonî : {{W+|pl|dzień|m-in}}, {{W+|pl|doba|m}} * Ponpeyî : {{W-|pon|rahn}} * Portugaliya kevn : {{W-|roa-opt|dia}} * Portugalî : {{W+|pt|dia|n}} * Puncabî : {{W-|pa|ਦਿਨ}} * Qazaxî : {{W+|kk|күн}}, {{W-|kk|тәулік}} * Qiptî : {{W-|cop|ⲉϩⲟⲟⲩ|n}} * Rawang : {{W-|raw|ni}} * Rohingyayî : {{W-|rhg|din}} * Romagnolî : {{W-|rgn|dè|n}} * Romancî : {{W-|rm|di}} * Romanyayî : {{W+|ro|zi|m}} * Rusî : {{W-|ru|су́тки|m-p}}, {{W+|ru|день|n}} * Rusînî : {{W-|rue|динь|m}} * Saho : {{W-|ssy|max|n}} * Saksoniya kevn : {{W-|osx|dag}} * Samiya bakurî : {{W-|se|beaivi}} * Sanskrîtî : {{W+|sa|दिन|nt}} * Santalî : {{W-|sat|ᱫᱤᱱ}} * Sardînî : {{W-|sc|dí}} * Sebwanoyî : {{W-|ceb|adlaw}} * Sicîlî : {{W+|scn|jornu|n}}, {{W+|scn|jonnu|n}} * Sidamo : {{W-|sid|barra}} * Sindhî : {{W-|sd|ڏينہن|tr=ḋīnhun|cuda=ڏيِنہُن}} * Sirananî : {{W-|srn|dei}} * Sirboxirwatî : *: Kirîlî: {{W-|sh|дан|n}} *: Latînî: {{W+|sh|dan|n}} * Sîlhetî : {{W-|syl|ꠖꠤꠘ}} * Slaviya kevn : {{W-|cu|дьнь|n}} * Slaviya rojavayî ya kevn : {{W-|orv|дьнь|n}} * Slovakî : {{W+|sk|doba|m}}, {{W+|sk|deň|n}} * Slovenî : {{W+|sl|dán|n}} * Somalî : {{W+|so|maalin}} * Sorbî: *: Sorbiya jêrîn : {{W-|dsb|źeń|n}} *: Sorbiya jorîn : {{W-|hsb|dźeń|n}} * South Slavey : {{W-|xsl|dzene}} * Southern Kalinga : {{W-|ksc|arkaw}}, {{W-|ksc|padcha}} * Spanî : {{W+|es|día|n}} * Sundanî : {{W-|su|dinten}} * Sûmerî : {{W-|sux|𒌓|tr=UD, U4}} * Swahîlî : {{W+|sw|siku}} * Swêdî : {{W+|sv|dygn|nt}}, {{W+|sv|dag|g}} * Şanî : {{W-|shn|ဝၼ်း}} * Şerpayî : {{W-|xsr|ཉི་མ}} * Tabasaranî : {{W-|tab|йигъ}} * Tacikî : {{W+|tg|рӯз}} * Tagalogî : {{W+|tl|araw}} * Tamîlî : {{W+|ta|நாள்}} * Tarantino : {{W-|roa-tar|giorne|n}}, {{W-|roa-tar|sciùrne|n}} * Tausug : {{W-|tsg|adlaw}} * Tayî : {{W+|th|วัน}} * Tayî nüa : {{W-|tdd|ᥝᥢᥰ}} * Telûgûyî : {{W+|te|రోజు}} * Temazîxtiya atlasa navendî : {{W-|tzm|ⴰⵙⵙ}} * Ternate : {{W-|tft|wange}} * Teteriya krîmî : {{W-|crh|kün}} * Teterî : {{W+|tt|көн}} * Tigrînî : {{W+|ti|መዓልቲ}} * Tirkî : {{W+|tr|gün}} * Tirkmenî : {{W-|tk|gün}} * Tîbetî : {{W-|bo|ཉི་མ}}, {{W-|bo|ཉིན}}, {{W-|bo|ཞག་པོ}}, {{W-|bo|ཞག}}, {{W-|bo|ཉིན་ཞག}} * Tsakonian : {{W-|tsd|αμέρα}} * Tumbukayî : {{W-|tum|dazi}} * Tuvanî : {{W-|tyv|хүн}} * Tzotzîlî : {{W-|tzo|kʼakʼal}} * Udi : {{W-|udi|гьи}} * Urdûyî : {{W-|ur|دن|n|tr=din}} * Ûkraynî : {{W+|uk|день|n}}, {{W-|uk|до́ба|m}} * Venîsî : {{W+|vec|dì}} * Vepsî : {{W-|vep|päiv}} * Viyetnamî : {{W+|vi|ngày}}, {{W+|vi|hôm}}, {{W+|vi|bữa}} * Volapûkî : {{W+|vo|del}} * Voroyî : {{W-|vro|päiv}} * Walonî : {{W+|wa|djoû|n}} * Western Bukidnon Manobo : {{W-|mbb|andew}} * Weylsî : {{W+|cy|dydd|n}}, {{W-|cy|dwthwn|n}}, {{W+|cy|diwrnod|n}} * Wînnebagoyî : {{W-|win|hąąp}}, {{W-|win|hąąpra|p}} * Wolofî : {{W-|wo|bés}} * Ximêrî : {{W+|km|ថ្ងៃ}}, {{W-|km|នៅពេលថ្ងៃ}} * Yagnobî : {{W-|yai|мет}}, {{W-|yai|рӯз}} * Yakan : {{W-|yka|bahangi}} * Yakutî : {{W-|sah|күн}}, {{W-|sah|хонук}} * Yidîşî : {{W+|yi|טאָג|n}} * Yorubayî : {{W-|yo|o̩jó̩}}, {{W-|yo|ò̩sán}} * Yûnanî : {{W+|el|ημέρα|m}}, {{W+|el|μέρα|m}}, {{W+|el|εικοσιτετράωρο|nt}}, {{W+|el|ημερονύχτιο|nt}} *: Kevn: {{W-|grc|ἡμέρα|m}}, {{W-|grc|ἦμαρ|nt}} * Zêlandî : {{W-|zea|dag|n}} * Zhuangî : {{W+|za|ngoenz}} * Zuluyî : {{W+|zu|usuku|c11|c10}}, {{W+|zu|umuhla|c3|c4}} * Zuniyî : {{W-|zun|yadonne}} * ǃXóõ : {{W-|nmn|ǁʻân}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb}} # {{ckb-Arab|ڕۆژ}} #* {{bêmînak|ckb}} == {{ziman|zza}} == === Navdêr === {{navdêr|zza|z=n}} # {{g|ku|roj|tr=-}} #* {{bêmînak|zza}} == {{ziman|mww}} == === Navdêr === {{navdêr|mww}} # {{f|mww|anatomî}} [[bez#ku|bez]] #* {{bêmînak|mww}} aayik5juncc0kkcn3s7jdcif0ddxqzv simbêl 0 3315 6347327 6336620 2026-08-31T10:03:23Z Wikihez 7344 guhartina pêşketî (DefSideBoxes); +Herwiha binêre (DefSideBoxes) (bi alîkarî) 6347327 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Nietzsche187a.jpg|thumb|Zilamekî bi '''simbêlên''' [[boq]]]] {{navdêr|ku|z=n}} # [[mû|Mû]]yên li [[jor]]a [[lêv]]ên [[zelam]]an [[şên]] dibin. #* {{J:Firat Cewerî:Girtî:1986|jêgirtin='''Simbêlê''' wî ser herdu lêvên wî girtibû û daketibû heta bi ser çenga wî.}} ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|سمبێل}} ==== Formên alternatîv ==== * {{g|ku|simêl}} ==== Jê ==== {{kol3|ku|cure=Jê |simbêl berdan<q:lêker> |simbêlberdan<q:navdêr> }} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|سمێڵ|tr=[[simêł]]}}, zaravayên başûrî [[sêwił]], şahzênî/şêxbizinî [[siwîl]], zazakî [[zimbêlî]], farisî {{g|fa|سبیل|tr=sibîl}} ji {{ji|ira}}. Belkî bi mecazî ji [[simbil]]. Herwiha bide ber erebiya misrî {{g|ar|شنب|tr=şeneb}}, îbrî {{g|he|שפם|tr=šapem}} + ermenî [[բեղ]] (bêł). ==== Bide ber ==== {{kol3|ku |simbil |simbol }} ==== Bi zaravayên din ==== * Kurmancî: zimbêl, simbêl, sêmbil, simbûl, simêl, simîl, simel * {{Z|ckb}}: simêll, simîl, siwêll, sêl * Kirmanckî/zazakî: zûmbuel, zûmbêl, zûmêl, zimbîl, zimbel, zimbelê, zîmêl, zimyel, zimel * Hewramî: simêll * Kirmaşanî/kelhûrî:siwîl * Feylî: siwêll * Lekî: siwêll ==== Werger ==== {{werger-ser}} * {{Z|ab}}: {{W-|ab|аԥаҵа}} * {{Z|ady}}: {{W-|ady|пакӏэхэр}} * {{Z|af}}: {{W-|af|snor}} * {{Z|sq}}: {{W+|sq|mustaqe|m}} * {{Z|pdc}}: {{W-|pdc|Schnarrbaart|n}}, {{W-|pdc|Schnauzbaart|n}}, {{W-|pdc|Schnurbaart|n}} * {{Z|de}}: {{W+|de|Schnurrbart|n}}, {{W+|de|Oberlippenbart|n}}, {{W+|de|Schnauzbart|n}}, {{W+|de|Schnauzer|n}}, {{W-|de|Schnäuzer|n}} * {{Z|an}}: {{W-|an|mostaixa|m}} * {{Z|arc}}: {{W-|arc|ܦܣܡܐ}} * {{Z|rup}}: {{W-|rup|mustatsã|m}} * {{Z|ast}}: {{W+|ast|bigote|n}} * {{Z|av}}: {{W-|av|михъал}} * {{Z|az}}: {{W+|az|bığ}} * {{Z|bjn}}: {{W-|bjn|sasingut}} * {{Z|eu}}: {{W-|eu|bibote}} * {{Z|ba}}: {{W-|ba|мыйыҡ}} * {{Z|sne}}: {{W-|sne|sumiet}} * {{Z|be}}: {{W-|be|вусы́|p}} * {{Z|bn}}: {{W-|bn|গোঁফ}} * {{Z|br}}: {{W+|br|mourroù}} * {{Z|kxd}}: {{W-|kxd|sumit}}, {{W-|kxd|kumis}} * {{Z|bg}}: {{W+|bg|муста́к|n}} * {{Z|my}}: {{W+|my|ကျင်စွယ်}} * {{Z|bua}}: {{W-|bua|һахал}} * {{Z|ce}}: {{W-|ce|мекхаш}}, {{W-|ce|мекхаш|p}} * {{Z|cs}}: {{W+|cs|knír|n}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|鬚|tr=sou1}} *: {{Z|cmn}}: {{W+|cmn|鬍子|tr=húzi}}, {{W+|cmn|髭|tr=zī}}, {{W-|cmn|八字鬍|tr=bāzìhú}} * {{Z|da}}: {{W+|da|overskæg|nt}} * {{Z|dv}}: {{W+|dv|މަތިމަސް}} * {{Z|id}}: {{W+|id|kumis}} * {{Z|ar}}: {{W-|ar|شَارِب|n}} *: {{Z|arz}}: {{W-|arz|شنب|n|tr=šanab}} *: {{Z|acw}}: {{W-|acw|شَنَب|n|tr=šanab}} *: {{Z|ary}}: {{W-|ary|شلغوم|tr=šalḡūm}} * {{Z|hy}}: {{W+|hy|բեղ}} * {{Z|eo}}: {{W+|eo|lipharoj|p}}, {{W-|eo|liphararo}} * {{Z|et}}: {{W-|et|vurrud|p}}, {{W-|et|vuntsid}} * {{Z|fa}}: {{W+|fa|بروت|tr=borut}}, {{W+|fa|سبیل|tr=sebil}} * {{Z|fo}}: {{W-|fo|yvirskegg|nt}} * {{Z|fi}}: {{W+|fi|viikset|p}}, {{W+|fi|viikset|cuda=viiksi-}} * {{Z|fr}}: {{W+|fr|moustache|m}}, {{W+|fr|bacchante|m}}, {{W+|fr|charmeuses|m-p}} * {{Z|gd}}: {{W-|gd|mustais|m}}, {{W-|gd|stais|m}}, {{W-|gd|balt|n}}, {{W-|gd|feusag-bheòil|m}}, {{W-|gd|ròibeag|m}}, {{W-|gd|réibean|n}}, {{W-|gd|ròibean|n}}, {{W-|gd|caisean-feusaig|n}} * {{Z|gl}}: {{W+|gl|bigote|n}}, {{W-|gl|bigode|n}}, {{W-|gl|mostacho|n}}, {{W-|gl|grañón|n}} * {{Z|gu}}: {{W+|gu|મુછ}} * {{Z|ka}}: {{W+|ka|ულვაში}}, {{W-|ka|ულვაშები}} * {{Z|gn}}: {{W-|gn|vigóte}} * {{Z|ht}}: {{W-|ht|moustach}} * {{Z|haw}}: {{W-|haw|ʻumiʻumi}} * {{Z|hi}}: {{W+|hi|मूँछ|m}}, {{W-|hi|मूछ|m}}, {{W+|hi|श्मश्रु}} * {{Z|mww}}: {{W-|mww|hwj-txwv}} * {{Z|nl}}: {{W+|nl|snor|m}} * {{Z|hrx}}: {{W-|hrx|Schnorres|n}} * {{Z|he}}: {{W+|he|שָׂפָם|n|tr=safam}} * {{Z|io}}: {{W-|io|mustacho}}, {{W+|io|labiobarbo}} * {{Z|ang}}: {{W-|ang|cenep|n}} * {{Z|en}}: {{W+|en|moustache}} * {{Z|ga}}: {{W+|ga|croiméal|n}} * {{Z|zai}}: {{W-|zai|guicha ruaa}} * {{Z|it}}: {{W+|it|baffi|n-p}}, {{W-|it|mostaccio|n}} * {{Z|is}}: {{W-|is|yfirvaraskegg|nt}}, {{W-|is|yfirskegg|nt}}, {{W+|is|motta|m}} * {{Z|ja}}: {{W+|ja|口ひげ|tr=くちひげ, kuchihige}}, {{W+|ja|口髭|tr=くちひげ, kuchihige}} * {{Z|jv}}: {{W+|jv|brengos}} * {{Z|jje}}: {{W-|jje|쉬염}}, {{W-|jje|시염}} * {{Z|kbd}}: {{W-|kbd|пащӏэ}} * {{Z|ca}}: {{W+|ca|bigoti}}, {{W+|ca|mostatxo|n}} * {{Z|ky}}: {{W+|ky|мурут}} * {{Z|ko}}: {{W+|ko|콧수염}}, {{W+|ko|수염}} * {{Z|kw}}: {{W-|kw|minvlew}} * {{Z|lbe}}: {{W-|lbe|ссирссилтту}} * {{Z|la}}: {{W-|la|mystax|n}}, {{W-|la|mustāceus|n}}, {{W-|la|subium|nt}} * {{Z|lv}}: {{W+|lv|ūsas|m-p}} * {{Z|lo}}: {{W-|lo|ມັດສຸ}} * {{Z|lzz}}: {{W-|lzz|ბუჲუღი}} * {{Z|lez}}: {{W-|lez|спел}} * {{Z|lt}}: {{W-|lt|ūsai|n-p}} * {{Z|lmo}}: {{W-|lmo|barbis|n}} * {{Z|mk}}: {{W-|mk|мустаќ|n}}, {{W-|mk|мустаќи|p}} * {{Z|ml}}: {{W+|ml|മീശ}} * {{Z|ms}}: {{W+|ms|misai}}, {{W-|ms|kumis}} * {{Z|mt}}: {{W-|mt|mustaċċi|n}} * {{Z|mi}}: {{W-|mi|hurungutu}} * {{Z|mr}}: {{W-|mr|मिशी}} * {{Z|hu}}: {{W+|hu|bajusz}} * {{Z|mel}}: {{W-|mel|sumih}}, {{W-|mel|gumei}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|живэр сахал}} * {{Z|mnw}}: {{W-|mnw|သော်ပါင်}} * {{Z|nv}}: {{W-|nv|dághá}} * {{Z|ne}}: {{W-|ne|जुँगा}}, {{W-|ne|जुंगा}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|bart|n}}, {{W-|nb|barter|n-p}}, {{W-|nb|mustasje|n}} *: {{Z|nn}}: {{W-|nn|bart|n}}, {{W-|nn|bartar|n-p}}, {{W-|nn|mustasje|n}} * {{Z|oc}}: {{W+|oc|mostacha|m}} * {{Z|or}}: {{W-|or|ମୁଛ}} * {{Z|os}}: {{W-|os|рихитӕ}} * {{Z|ota}}: {{W-|ota|بیق|tr=bıyık}}, {{W-|ota|سبله|tr=sebele}} * {{Z|ug}}: {{W-|ug|بۇرۇت}} * {{Z|uz}}: {{W+|uz|moʻylab}}, {{W+|uz|burut}} * {{Z|ps}}: {{W+|ps|برېت|n-p|tr=bret}} * {{Z|pdt}}: {{W-|pdt|Schnurboat|n}} * {{Z|pl}}: {{W-|pl|wąsy|n-p}} * {{Z|pt}}: {{W+|pt|bigode|n}} * {{Z|pa}}: {{W-|pa|ਮੁੱਛ|m}} * {{Z|kk}}: {{W-|kk|мұрт}} * {{Z|ro}}: {{W+|ro|mustață|m}} * {{Z|ru}}: {{W+|ru|ус|n}}, {{W+|ru|усы́|n-p}} * Samî: *: {{Z|smn}}: {{W-|smn|njävileh}} *: {{Z|sjd}}: {{W-|sjd|оа̄б}} *: {{Z|sms}}: {{W-|sms|ääʹbben}} *: {{Z|sjt}}: {{W-|sjt|а̄бн}} * {{Z|sa}}: {{W+|sa|श्मश्रु}} * Sardinian: *: {{Z|sc}}: {{W-|sc|mustatzus}} *: {{Z|sc}}: {{W-|sc|mustatzus}} * {{Z|scn}}: {{W+|scn|mustazzu|n}}, {{W+|scn|mustazzi|n-p}}, {{W-|scn|baffi|n-p}} * {{Z|sd}}: {{W-|sd|مُڇ|m|tr=mucha}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|бр̑к|n}}, {{W-|sh|бр̏кови|n-p}}, {{W-|sh|наусница|cuda=на̀уснице|m-p}} *: Latînî: {{W+|sh|bȓk|n}}, {{W+|sh|bȑkovi|n-p}}, {{W+|sh|nausnica|cuda=nàusnice|m-p}} * {{Z|sco}}: {{W-|sco|mouser}}, {{W-|sco|moutash}} * {{Z|sk}}: {{W-|sk|fúzy|n-p}}, {{W+|sk|fúz|n}} * {{Z|sl}}: {{W+|sl|brki|n-p}} * {{Z|so}}: {{W-|so|shaarbo}} * {{Z|es}}: {{W+|es|bigote|n}}, {{W+|es|mostacho|n}} * {{Z|sw}}: {{W-|sw|masharubu|p}} * {{Z|sv}}: {{W+|sv|mustasch|g}} * {{Z|tg}}: {{W-|tg|мӯйлаб}}, {{W-|tg|бурут}} * {{Z|tl}}: {{W-|tl|misay}}, {{W+|tl|bigote}} * {{Z|ta}}: {{W+|ta|மீசை}} * {{Z|th}}: {{W+|th|มัสสุ}}, {{W-|th|ทาฐิกะ}}, {{W+|th|หนวด}} * {{Z|te}}: {{W+|te|మీసం}} * {{Z|tt}}: {{W+|tt|мыек}} * {{Z|tr}}: {{W+|tr|bıyık}} * {{Z|tk}}: {{W-|tk|murt}} * {{Z|bo}}: {{W-|bo|ཁ་སྤུ}}, {{W-|bo|སྨ་ར}}, {{W-|bo|འ་ར}} * {{Z|tyv}}: {{W-|tyv|сал}} * {{Z|udi}}: {{W-|udi|быгъ}}, {{W-|udi|бигъ}} * {{Z|ur}}: {{W-|ur|مونچھ|m|tr=mūñch}} * {{Z|uk}}: {{W-|uk|ву́са|p}}, {{W-|uk|ву́си|p}} * {{Z|vec}}: {{W-|vec|bafo}} * {{Z|vep}}: {{W-|vep|habinod}} * {{Z|vi}}: {{W+|vi|râu mép}}, {{W-|vi|ria mép}}, {{W+|vi|ria}} * {{Z|vo}}: {{W-|vo|mustag}} * {{Z|wa}}: {{W+|wa|moustatche}} * {{Z|cy}}: {{W-|cy|trawswch|n}}, {{W+|cy|mwstas|n}} * {{Z|km}}: {{W+|km|ពុកមាត់}} * {{Z|yi}}: {{W-|yi|וואָנצעס|n}} * {{Z|yo}}: {{W-|yo|máàmu}}, {{W-|yo|mámu}}, {{W-|yo|irun ètè}}, {{W-|yo|irun-imu}}, {{W-|yo|túbọ̀mú}} * {{Z|pnt}}: {{W-|pnt|μουστάκιν}} * {{Z|el}}: {{W+|el|μουστάκι|nt}} *: Kevn: {{W-|grc|μύσταξ|n}}, {{W-|grc|ὑπήνη|m}} {{werger-bin}} :{{werger çavkanî|en|moustache|beş=Ev qismê Wergerê|oldid=75582865}} ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |simbêlboq |simbêlqeytan }} 40r17ht863cxlv9jyve3xzx6a47k0ki 6347335 6347327 2026-08-31T10:41:15Z Balyozbot 7867 [[Special:PermanentLink/6298023|Bot]]: rêzkirina beşan 6347335 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Nietzsche187a.jpg|thumb|Zilamekî bi '''simbêlên''' [[boq]]]] {{navdêr|ku|z=n}} # [[mû|Mû]]yên li [[jor]]a [[lêv]]ên [[zelam]]an [[şên]] dibin. #* {{J:Firat Cewerî:Girtî:1986|jêgirtin='''Simbêlê''' wî ser herdu lêvên wî girtibû û daketibû heta bi ser çenga wî.}} ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|سمبێل}} ==== Formên alternatîv ==== * {{g|ku|simêl}} ==== Jê ==== {{kol3|ku|cure=Jê |simbêl berdan<q:lêker> |simbêlberdan<q:navdêr> }} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|سمێڵ|tr=[[simêł]]}}, zaravayên başûrî [[sêwił]], şahzênî/şêxbizinî [[siwîl]], zazakî [[zimbêlî]], farisî {{g|fa|سبیل|tr=sibîl}} ji {{ji|ira}}. Belkî bi mecazî ji [[simbil]]. Herwiha bide ber erebiya misrî {{g|ar|شنب|tr=şeneb}}, îbrî {{g|he|שפם|tr=šapem}} + ermenî [[բեղ]] (bêł). ==== Bide ber ==== {{kol3|ku |simbil |simbol }} ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |simbêlboq |simbêlqeytan }} ==== Bi zaravayên din ==== * Kurmancî: zimbêl, simbêl, sêmbil, simbûl, simêl, simîl, simel * {{Z|ckb}}: simêll, simîl, siwêll, sêl * Kirmanckî/zazakî: zûmbuel, zûmbêl, zûmêl, zimbîl, zimbel, zimbelê, zîmêl, zimyel, zimel * Hewramî: simêll * Kirmaşanî/kelhûrî:siwîl * Feylî: siwêll * Lekî: siwêll ==== Werger ==== {{werger-ser}} * {{Z|ab}}: {{W-|ab|аԥаҵа}} * {{Z|ady}}: {{W-|ady|пакӏэхэр}} * {{Z|af}}: {{W-|af|snor}} * {{Z|sq}}: {{W+|sq|mustaqe|m}} * {{Z|pdc}}: {{W-|pdc|Schnarrbaart|n}}, {{W-|pdc|Schnauzbaart|n}}, {{W-|pdc|Schnurbaart|n}} * {{Z|de}}: {{W+|de|Schnurrbart|n}}, {{W+|de|Oberlippenbart|n}}, {{W+|de|Schnauzbart|n}}, {{W+|de|Schnauzer|n}}, {{W-|de|Schnäuzer|n}} * {{Z|an}}: {{W-|an|mostaixa|m}} * {{Z|arc}}: {{W-|arc|ܦܣܡܐ}} * {{Z|rup}}: {{W-|rup|mustatsã|m}} * {{Z|ast}}: {{W+|ast|bigote|n}} * {{Z|av}}: {{W-|av|михъал}} * {{Z|az}}: {{W+|az|bığ}} * {{Z|bjn}}: {{W-|bjn|sasingut}} * {{Z|eu}}: {{W-|eu|bibote}} * {{Z|ba}}: {{W-|ba|мыйыҡ}} * {{Z|sne}}: {{W-|sne|sumiet}} * {{Z|be}}: {{W-|be|вусы́|p}} * {{Z|bn}}: {{W-|bn|গোঁফ}} * {{Z|br}}: {{W+|br|mourroù}} * {{Z|kxd}}: {{W-|kxd|sumit}}, {{W-|kxd|kumis}} * {{Z|bg}}: {{W+|bg|муста́к|n}} * {{Z|my}}: {{W+|my|ကျင်စွယ်}} * {{Z|bua}}: {{W-|bua|һахал}} * {{Z|ce}}: {{W-|ce|мекхаш}}, {{W-|ce|мекхаш|p}} * {{Z|cs}}: {{W+|cs|knír|n}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|鬚|tr=sou1}} *: {{Z|cmn}}: {{W+|cmn|鬍子|tr=húzi}}, {{W+|cmn|髭|tr=zī}}, {{W-|cmn|八字鬍|tr=bāzìhú}} * {{Z|da}}: {{W+|da|overskæg|nt}} * {{Z|dv}}: {{W+|dv|މަތިމަސް}} * {{Z|id}}: {{W+|id|kumis}} * {{Z|ar}}: {{W-|ar|شَارِب|n}} *: {{Z|arz}}: {{W-|arz|شنب|n|tr=šanab}} *: {{Z|acw}}: {{W-|acw|شَنَب|n|tr=šanab}} *: {{Z|ary}}: {{W-|ary|شلغوم|tr=šalḡūm}} * {{Z|hy}}: {{W+|hy|բեղ}} * {{Z|eo}}: {{W+|eo|lipharoj|p}}, {{W-|eo|liphararo}} * {{Z|et}}: {{W-|et|vurrud|p}}, {{W-|et|vuntsid}} * {{Z|fa}}: {{W+|fa|بروت|tr=borut}}, {{W+|fa|سبیل|tr=sebil}} * {{Z|fo}}: {{W-|fo|yvirskegg|nt}} * {{Z|fi}}: {{W+|fi|viikset|p}}, {{W+|fi|viikset|cuda=viiksi-}} * {{Z|fr}}: {{W+|fr|moustache|m}}, {{W+|fr|bacchante|m}}, {{W+|fr|charmeuses|m-p}} * {{Z|gd}}: {{W-|gd|mustais|m}}, {{W-|gd|stais|m}}, {{W-|gd|balt|n}}, {{W-|gd|feusag-bheòil|m}}, {{W-|gd|ròibeag|m}}, {{W-|gd|réibean|n}}, {{W-|gd|ròibean|n}}, {{W-|gd|caisean-feusaig|n}} * {{Z|gl}}: {{W+|gl|bigote|n}}, {{W-|gl|bigode|n}}, {{W-|gl|mostacho|n}}, {{W-|gl|grañón|n}} * {{Z|gu}}: {{W+|gu|મુછ}} * {{Z|ka}}: {{W+|ka|ულვაში}}, {{W-|ka|ულვაშები}} * {{Z|gn}}: {{W-|gn|vigóte}} * {{Z|ht}}: {{W-|ht|moustach}} * {{Z|haw}}: {{W-|haw|ʻumiʻumi}} * {{Z|hi}}: {{W+|hi|मूँछ|m}}, {{W-|hi|मूछ|m}}, {{W+|hi|श्मश्रु}} * {{Z|mww}}: {{W-|mww|hwj-txwv}} * {{Z|nl}}: {{W+|nl|snor|m}} * {{Z|hrx}}: {{W-|hrx|Schnorres|n}} * {{Z|he}}: {{W+|he|שָׂפָם|n|tr=safam}} * {{Z|io}}: {{W-|io|mustacho}}, {{W+|io|labiobarbo}} * {{Z|ang}}: {{W-|ang|cenep|n}} * {{Z|en}}: {{W+|en|moustache}} * {{Z|ga}}: {{W+|ga|croiméal|n}} * {{Z|zai}}: {{W-|zai|guicha ruaa}} * {{Z|it}}: {{W+|it|baffi|n-p}}, {{W-|it|mostaccio|n}} * {{Z|is}}: {{W-|is|yfirvaraskegg|nt}}, {{W-|is|yfirskegg|nt}}, {{W+|is|motta|m}} * {{Z|ja}}: {{W+|ja|口ひげ|tr=くちひげ, kuchihige}}, {{W+|ja|口髭|tr=くちひげ, kuchihige}} * {{Z|jv}}: {{W+|jv|brengos}} * {{Z|jje}}: {{W-|jje|쉬염}}, {{W-|jje|시염}} * {{Z|kbd}}: {{W-|kbd|пащӏэ}} * {{Z|ca}}: {{W+|ca|bigoti}}, {{W+|ca|mostatxo|n}} * {{Z|ky}}: {{W+|ky|мурут}} * {{Z|ko}}: {{W+|ko|콧수염}}, {{W+|ko|수염}} * {{Z|kw}}: {{W-|kw|minvlew}} * {{Z|lbe}}: {{W-|lbe|ссирссилтту}} * {{Z|la}}: {{W-|la|mystax|n}}, {{W-|la|mustāceus|n}}, {{W-|la|subium|nt}} * {{Z|lv}}: {{W+|lv|ūsas|m-p}} * {{Z|lo}}: {{W-|lo|ມັດສຸ}} * {{Z|lzz}}: {{W-|lzz|ბუჲუღი}} * {{Z|lez}}: {{W-|lez|спел}} * {{Z|lt}}: {{W-|lt|ūsai|n-p}} * {{Z|lmo}}: {{W-|lmo|barbis|n}} * {{Z|mk}}: {{W-|mk|мустаќ|n}}, {{W-|mk|мустаќи|p}} * {{Z|ml}}: {{W+|ml|മീശ}} * {{Z|ms}}: {{W+|ms|misai}}, {{W-|ms|kumis}} * {{Z|mt}}: {{W-|mt|mustaċċi|n}} * {{Z|mi}}: {{W-|mi|hurungutu}} * {{Z|mr}}: {{W-|mr|मिशी}} * {{Z|hu}}: {{W+|hu|bajusz}} * {{Z|mel}}: {{W-|mel|sumih}}, {{W-|mel|gumei}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|живэр сахал}} * {{Z|mnw}}: {{W-|mnw|သော်ပါင်}} * {{Z|nv}}: {{W-|nv|dághá}} * {{Z|ne}}: {{W-|ne|जुँगा}}, {{W-|ne|जुंगा}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|bart|n}}, {{W-|nb|barter|n-p}}, {{W-|nb|mustasje|n}} *: {{Z|nn}}: {{W-|nn|bart|n}}, {{W-|nn|bartar|n-p}}, {{W-|nn|mustasje|n}} * {{Z|oc}}: {{W+|oc|mostacha|m}} * {{Z|or}}: {{W-|or|ମୁଛ}} * {{Z|os}}: {{W-|os|рихитӕ}} * {{Z|ota}}: {{W-|ota|بیق|tr=bıyık}}, {{W-|ota|سبله|tr=sebele}} * {{Z|ug}}: {{W-|ug|بۇرۇت}} * {{Z|uz}}: {{W+|uz|moʻylab}}, {{W+|uz|burut}} * {{Z|ps}}: {{W+|ps|برېت|n-p|tr=bret}} * {{Z|pdt}}: {{W-|pdt|Schnurboat|n}} * {{Z|pl}}: {{W-|pl|wąsy|n-p}} * {{Z|pt}}: {{W+|pt|bigode|n}} * {{Z|pa}}: {{W-|pa|ਮੁੱਛ|m}} * {{Z|kk}}: {{W-|kk|мұрт}} * {{Z|ro}}: {{W+|ro|mustață|m}} * {{Z|ru}}: {{W+|ru|ус|n}}, {{W+|ru|усы́|n-p}} * Samî: *: {{Z|smn}}: {{W-|smn|njävileh}} *: {{Z|sjd}}: {{W-|sjd|оа̄б}} *: {{Z|sms}}: {{W-|sms|ääʹbben}} *: {{Z|sjt}}: {{W-|sjt|а̄бн}} * {{Z|sa}}: {{W+|sa|श्मश्रु}} * Sardinian: *: {{Z|sc}}: {{W-|sc|mustatzus}} *: {{Z|sc}}: {{W-|sc|mustatzus}} * {{Z|scn}}: {{W+|scn|mustazzu|n}}, {{W+|scn|mustazzi|n-p}}, {{W-|scn|baffi|n-p}} * {{Z|sd}}: {{W-|sd|مُڇ|m|tr=mucha}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|бр̑к|n}}, {{W-|sh|бр̏кови|n-p}}, {{W-|sh|наусница|cuda=на̀уснице|m-p}} *: Latînî: {{W+|sh|bȓk|n}}, {{W+|sh|bȑkovi|n-p}}, {{W+|sh|nausnica|cuda=nàusnice|m-p}} * {{Z|sco}}: {{W-|sco|mouser}}, {{W-|sco|moutash}} * {{Z|sk}}: {{W-|sk|fúzy|n-p}}, {{W+|sk|fúz|n}} * {{Z|sl}}: {{W+|sl|brki|n-p}} * {{Z|so}}: {{W-|so|shaarbo}} * {{Z|es}}: {{W+|es|bigote|n}}, {{W+|es|mostacho|n}} * {{Z|sw}}: {{W-|sw|masharubu|p}} * {{Z|sv}}: {{W+|sv|mustasch|g}} * {{Z|tg}}: {{W-|tg|мӯйлаб}}, {{W-|tg|бурут}} * {{Z|tl}}: {{W-|tl|misay}}, {{W+|tl|bigote}} * {{Z|ta}}: {{W+|ta|மீசை}} * {{Z|th}}: {{W+|th|มัสสุ}}, {{W-|th|ทาฐิกะ}}, {{W+|th|หนวด}} * {{Z|te}}: {{W+|te|మీసం}} * {{Z|tt}}: {{W+|tt|мыек}} * {{Z|tr}}: {{W+|tr|bıyık}} * {{Z|tk}}: {{W-|tk|murt}} * {{Z|bo}}: {{W-|bo|ཁ་སྤུ}}, {{W-|bo|སྨ་ར}}, {{W-|bo|འ་ར}} * {{Z|tyv}}: {{W-|tyv|сал}} * {{Z|udi}}: {{W-|udi|быгъ}}, {{W-|udi|бигъ}} * {{Z|ur}}: {{W-|ur|مونچھ|m|tr=mūñch}} * {{Z|uk}}: {{W-|uk|ву́са|p}}, {{W-|uk|ву́си|p}} * {{Z|vec}}: {{W-|vec|bafo}} * {{Z|vep}}: {{W-|vep|habinod}} * {{Z|vi}}: {{W+|vi|râu mép}}, {{W-|vi|ria mép}}, {{W+|vi|ria}} * {{Z|vo}}: {{W-|vo|mustag}} * {{Z|wa}}: {{W+|wa|moustatche}} * {{Z|cy}}: {{W-|cy|trawswch|n}}, {{W+|cy|mwstas|n}} * {{Z|km}}: {{W+|km|ពុកមាត់}} * {{Z|yi}}: {{W-|yi|וואָנצעס|n}} * {{Z|yo}}: {{W-|yo|máàmu}}, {{W-|yo|mámu}}, {{W-|yo|irun ètè}}, {{W-|yo|irun-imu}}, {{W-|yo|túbọ̀mú}} * {{Z|pnt}}: {{W-|pnt|μουστάκιν}} * {{Z|el}}: {{W+|el|μουστάκι|nt}} *: Kevn: {{W-|grc|μύσταξ|n}}, {{W-|grc|ὑπήνη|m}} {{werger-bin}} :{{werger çavkanî|en|moustache|beş=Ev qismê Wergerê|oldid=75582865}} kiqe9pk7cj6092ndfluizcsibr6zv11 6347338 6347335 2026-08-31T11:12:12Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347338 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Nietzsche187a.jpg|thumb|Zilamekî bi '''simbêlên''' [[boq]]]] {{navdêr|ku|z=n}} # [[mû|Mûyên]] li [[jor]]a [[lêv]]ên [[zelam]]an [[şên]] dibin. #* {{J:Firat Cewerî:Girtî:1986|jêgirtin='''Simbêlê''' wî ser herdu lêvên wî girtibû û daketibû heta bi ser çenga wî.}} ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|سمبێل}} ==== Formên alternatîv ==== * {{g|ku|simêl}} ==== Jê ==== {{kol3|ku|cure=Jê |simbêl berdan<q:lêker> |simbêlberdan<q:navdêr> }} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|سمێڵ|tr=[[simêł]]}}, zaravayên başûrî [[sêwił]], şahzênî/şêxbizinî [[siwîl]], zazakî [[zimbêlî]], farisî {{g|fa|سبیل|tr=sibîl}} ji {{ji|ira}}. Belkî bi mecazî ji [[simbil]]. Herwiha bide ber erebiya misrî {{g|ar|شنب|tr=şeneb}}, îbrî {{g|he|שפם|tr=šapem}} + ermenî [[բեղ]] (bêł). ==== Bide ber ==== {{kol3|ku |simbil |simbol }} ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |simbêlboq |simbêlqeytan }} ==== Bi zaravayên din ==== * Kurmancî: zimbêl, simbêl, sêmbil, simbûl, simêl, simîl, simel * {{Z|ckb}}: simêll, simîl, siwêll, sêl * Kirmanckî/zazakî: zûmbuel, zûmbêl, zûmêl, zimbîl, zimbel, zimbelê, zîmêl, zimyel, zimel * Hewramî: simêll * Kirmaşanî/kelhûrî:siwîl * Feylî: siwêll * Lekî: siwêll ==== Werger ==== {{werger-ser}} * {{Z|ab}}: {{W-|ab|аԥаҵа}} * {{Z|ady}}: {{W-|ady|пакӏэхэр}} * {{Z|af}}: {{W-|af|snor}} * {{Z|sq}}: {{W+|sq|mustaqe|m}} * {{Z|pdc}}: {{W-|pdc|Schnarrbaart|n}}, {{W-|pdc|Schnauzbaart|n}}, {{W-|pdc|Schnurbaart|n}} * {{Z|de}}: {{W+|de|Schnurrbart|n}}, {{W+|de|Oberlippenbart|n}}, {{W+|de|Schnauzbart|n}}, {{W+|de|Schnauzer|n}}, {{W-|de|Schnäuzer|n}} * {{Z|an}}: {{W-|an|mostaixa|m}} * {{Z|arc}}: {{W-|arc|ܦܣܡܐ}} * {{Z|rup}}: {{W-|rup|mustatsã|m}} * {{Z|ast}}: {{W+|ast|bigote|n}} * {{Z|av}}: {{W-|av|михъал}} * {{Z|az}}: {{W+|az|bığ}} * {{Z|bjn}}: {{W-|bjn|sasingut}} * {{Z|eu}}: {{W-|eu|bibote}} * {{Z|ba}}: {{W-|ba|мыйыҡ}} * {{Z|sne}}: {{W-|sne|sumiet}} * {{Z|be}}: {{W-|be|вусы́|p}} * {{Z|bn}}: {{W-|bn|গোঁফ}} * {{Z|br}}: {{W+|br|mourroù}} * {{Z|kxd}}: {{W-|kxd|sumit}}, {{W-|kxd|kumis}} * {{Z|bg}}: {{W+|bg|муста́к|n}} * {{Z|my}}: {{W+|my|ကျင်စွယ်}} * {{Z|bua}}: {{W-|bua|һахал}} * {{Z|ce}}: {{W-|ce|мекхаш}}, {{W-|ce|мекхаш|p}} * {{Z|cs}}: {{W+|cs|knír|n}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|鬚|tr=sou1}} *: {{Z|cmn}}: {{W+|cmn|鬍子|tr=húzi}}, {{W+|cmn|髭|tr=zī}}, {{W-|cmn|八字鬍|tr=bāzìhú}} * {{Z|da}}: {{W+|da|overskæg|nt}} * {{Z|dv}}: {{W+|dv|މަތިމަސް}} * {{Z|id}}: {{W+|id|kumis}} * {{Z|ar}}: {{W-|ar|شَارِب|n}} *: {{Z|arz}}: {{W-|arz|شنب|n|tr=šanab}} *: {{Z|acw}}: {{W-|acw|شَنَب|n|tr=šanab}} *: {{Z|ary}}: {{W-|ary|شلغوم|tr=šalḡūm}} * {{Z|hy}}: {{W+|hy|բեղ}} * {{Z|eo}}: {{W+|eo|lipharoj|p}}, {{W-|eo|liphararo}} * {{Z|et}}: {{W-|et|vurrud|p}}, {{W-|et|vuntsid}} * {{Z|fa}}: {{W+|fa|بروت|tr=borut}}, {{W+|fa|سبیل|tr=sebil}} * {{Z|fo}}: {{W-|fo|yvirskegg|nt}} * {{Z|fi}}: {{W+|fi|viikset|p}}, {{W+|fi|viikset|cuda=viiksi-}} * {{Z|fr}}: {{W+|fr|moustache|m}}, {{W+|fr|bacchante|m}}, {{W+|fr|charmeuses|m-p}} * {{Z|gd}}: {{W-|gd|mustais|m}}, {{W-|gd|stais|m}}, {{W-|gd|balt|n}}, {{W-|gd|feusag-bheòil|m}}, {{W-|gd|ròibeag|m}}, {{W-|gd|réibean|n}}, {{W-|gd|ròibean|n}}, {{W-|gd|caisean-feusaig|n}} * {{Z|gl}}: {{W+|gl|bigote|n}}, {{W-|gl|bigode|n}}, {{W-|gl|mostacho|n}}, {{W-|gl|grañón|n}} * {{Z|gu}}: {{W+|gu|મુછ}} * {{Z|ka}}: {{W+|ka|ულვაში}}, {{W-|ka|ულვაშები}} * {{Z|gn}}: {{W-|gn|vigóte}} * {{Z|ht}}: {{W-|ht|moustach}} * {{Z|haw}}: {{W-|haw|ʻumiʻumi}} * {{Z|hi}}: {{W+|hi|मूँछ|m}}, {{W-|hi|मूछ|m}}, {{W+|hi|श्मश्रु}} * {{Z|mww}}: {{W-|mww|hwj-txwv}} * {{Z|nl}}: {{W+|nl|snor|m}} * {{Z|hrx}}: {{W-|hrx|Schnorres|n}} * {{Z|he}}: {{W+|he|שָׂפָם|n|tr=safam}} * {{Z|io}}: {{W-|io|mustacho}}, {{W+|io|labiobarbo}} * {{Z|ang}}: {{W-|ang|cenep|n}} * {{Z|en}}: {{W+|en|moustache}} * {{Z|ga}}: {{W+|ga|croiméal|n}} * {{Z|zai}}: {{W-|zai|guicha ruaa}} * {{Z|it}}: {{W+|it|baffi|n-p}}, {{W-|it|mostaccio|n}} * {{Z|is}}: {{W-|is|yfirvaraskegg|nt}}, {{W-|is|yfirskegg|nt}}, {{W+|is|motta|m}} * {{Z|ja}}: {{W+|ja|口ひげ|tr=くちひげ, kuchihige}}, {{W+|ja|口髭|tr=くちひげ, kuchihige}} * {{Z|jv}}: {{W+|jv|brengos}} * {{Z|jje}}: {{W-|jje|쉬염}}, {{W-|jje|시염}} * {{Z|kbd}}: {{W-|kbd|пащӏэ}} * {{Z|ca}}: {{W+|ca|bigoti}}, {{W+|ca|mostatxo|n}} * {{Z|ky}}: {{W+|ky|мурут}} * {{Z|ko}}: {{W+|ko|콧수염}}, {{W+|ko|수염}} * {{Z|kw}}: {{W-|kw|minvlew}} * {{Z|lbe}}: {{W-|lbe|ссирссилтту}} * {{Z|la}}: {{W-|la|mystax|n}}, {{W-|la|mustāceus|n}}, {{W-|la|subium|nt}} * {{Z|lv}}: {{W+|lv|ūsas|m-p}} * {{Z|lo}}: {{W-|lo|ມັດສຸ}} * {{Z|lzz}}: {{W-|lzz|ბუჲუღი}} * {{Z|lez}}: {{W-|lez|спел}} * {{Z|lt}}: {{W-|lt|ūsai|n-p}} * {{Z|lmo}}: {{W-|lmo|barbis|n}} * {{Z|mk}}: {{W-|mk|мустаќ|n}}, {{W-|mk|мустаќи|p}} * {{Z|ml}}: {{W+|ml|മീശ}} * {{Z|ms}}: {{W+|ms|misai}}, {{W-|ms|kumis}} * {{Z|mt}}: {{W-|mt|mustaċċi|n}} * {{Z|mi}}: {{W-|mi|hurungutu}} * {{Z|mr}}: {{W-|mr|मिशी}} * {{Z|hu}}: {{W+|hu|bajusz}} * {{Z|mel}}: {{W-|mel|sumih}}, {{W-|mel|gumei}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|живэр сахал}} * {{Z|mnw}}: {{W-|mnw|သော်ပါင်}} * {{Z|nv}}: {{W-|nv|dághá}} * {{Z|ne}}: {{W-|ne|जुँगा}}, {{W-|ne|जुंगा}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|bart|n}}, {{W-|nb|barter|n-p}}, {{W-|nb|mustasje|n}} *: {{Z|nn}}: {{W-|nn|bart|n}}, {{W-|nn|bartar|n-p}}, {{W-|nn|mustasje|n}} * {{Z|oc}}: {{W+|oc|mostacha|m}} * {{Z|or}}: {{W-|or|ମୁଛ}} * {{Z|os}}: {{W-|os|рихитӕ}} * {{Z|ota}}: {{W-|ota|بیق|tr=bıyık}}, {{W-|ota|سبله|tr=sebele}} * {{Z|ug}}: {{W-|ug|بۇرۇت}} * {{Z|uz}}: {{W+|uz|moʻylab}}, {{W+|uz|burut}} * {{Z|ps}}: {{W+|ps|برېت|n-p|tr=bret}} * {{Z|pdt}}: {{W-|pdt|Schnurboat|n}} * {{Z|pl}}: {{W-|pl|wąsy|n-p}} * {{Z|pt}}: {{W+|pt|bigode|n}} * {{Z|pa}}: {{W-|pa|ਮੁੱਛ|m}} * {{Z|kk}}: {{W-|kk|мұрт}} * {{Z|ro}}: {{W+|ro|mustață|m}} * {{Z|ru}}: {{W+|ru|ус|n}}, {{W+|ru|усы́|n-p}} * Samî: *: {{Z|smn}}: {{W-|smn|njävileh}} *: {{Z|sjd}}: {{W-|sjd|оа̄б}} *: {{Z|sms}}: {{W-|sms|ääʹbben}} *: {{Z|sjt}}: {{W-|sjt|а̄бн}} * {{Z|sa}}: {{W+|sa|श्मश्रु}} * Sardinian: *: {{Z|sc}}: {{W-|sc|mustatzus}} *: {{Z|sc}}: {{W-|sc|mustatzus}} * {{Z|scn}}: {{W+|scn|mustazzu|n}}, {{W+|scn|mustazzi|n-p}}, {{W-|scn|baffi|n-p}} * {{Z|sd}}: {{W-|sd|مُڇ|m|tr=mucha}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|бр̑к|n}}, {{W-|sh|бр̏кови|n-p}}, {{W-|sh|наусница|cuda=на̀уснице|m-p}} *: Latînî: {{W+|sh|bȓk|n}}, {{W+|sh|bȑkovi|n-p}}, {{W+|sh|nausnica|cuda=nàusnice|m-p}} * {{Z|sco}}: {{W-|sco|mouser}}, {{W-|sco|moutash}} * {{Z|sk}}: {{W-|sk|fúzy|n-p}}, {{W+|sk|fúz|n}} * {{Z|sl}}: {{W+|sl|brki|n-p}} * {{Z|so}}: {{W-|so|shaarbo}} * {{Z|es}}: {{W+|es|bigote|n}}, {{W+|es|mostacho|n}} * {{Z|sw}}: {{W-|sw|masharubu|p}} * {{Z|sv}}: {{W+|sv|mustasch|g}} * {{Z|tg}}: {{W-|tg|мӯйлаб}}, {{W-|tg|бурут}} * {{Z|tl}}: {{W-|tl|misay}}, {{W+|tl|bigote}} * {{Z|ta}}: {{W+|ta|மீசை}} * {{Z|th}}: {{W+|th|มัสสุ}}, {{W-|th|ทาฐิกะ}}, {{W+|th|หนวด}} * {{Z|te}}: {{W+|te|మీసం}} * {{Z|tt}}: {{W+|tt|мыек}} * {{Z|tr}}: {{W+|tr|bıyık}} * {{Z|tk}}: {{W-|tk|murt}} * {{Z|bo}}: {{W-|bo|ཁ་སྤུ}}, {{W-|bo|སྨ་ར}}, {{W-|bo|འ་ར}} * {{Z|tyv}}: {{W-|tyv|сал}} * {{Z|udi}}: {{W-|udi|быгъ}}, {{W-|udi|бигъ}} * {{Z|ur}}: {{W-|ur|مونچھ|m|tr=mūñch}} * {{Z|uk}}: {{W-|uk|ву́са|p}}, {{W-|uk|ву́си|p}} * {{Z|vec}}: {{W-|vec|bafo}} * {{Z|vep}}: {{W-|vep|habinod}} * {{Z|vi}}: {{W+|vi|râu mép}}, {{W-|vi|ria mép}}, {{W+|vi|ria}} * {{Z|vo}}: {{W-|vo|mustag}} * {{Z|wa}}: {{W+|wa|moustatche}} * {{Z|cy}}: {{W-|cy|trawswch|n}}, {{W+|cy|mwstas|n}} * {{Z|km}}: {{W+|km|ពុកមាត់}} * {{Z|yi}}: {{W-|yi|וואָנצעס|n}} * {{Z|yo}}: {{W-|yo|máàmu}}, {{W-|yo|mámu}}, {{W-|yo|irun ètè}}, {{W-|yo|irun-imu}}, {{W-|yo|túbọ̀mú}} * {{Z|pnt}}: {{W-|pnt|μουστάκιν}} * {{Z|el}}: {{W+|el|μουστάκι|nt}} *: Kevn: {{W-|grc|μύσταξ|n}}, {{W-|grc|ὑπήνη|m}} {{werger-bin}} :{{werger çavkanî|en|moustache|beş=Ev qismê Wergerê|oldid=75582865}} pz9s5pnbz9p1lxq81zotstejxztwhd7 kitêb 0 3503 6347275 6337585 2026-08-30T22:08:32Z Wikihez 7344 +nimûneya bikaranînê bi amûra « [[Mediawiki:Gadget-wikt.add-examples|Nimûne zêde bike]] » (v2.0). 6347275 wikitext text/x-wiki {{bnr-h|kiteb|Kitêb}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA|k(h)itêb}} * {{deng|ku|LL-Q36163 (kmr)-Ebulfîda-kitêb.wav|dever=Bidlîs}} * {{ku-kîte}} === Navdêr === [[Wêne:Latin_dictionary.jpg|thumb|Kitêb]] {{navdêr|ku|z=m}} # [[kom|Komeke]] [[kaxez]]ên bi [[nivîs]] û / yan [[resm]] yên di nav [[berg]]ekî de hatine [[çap]]kirin. #: {{hevmane|ku|pirtûk}} #: {{mk|ku|Wê rûpela 50 ya '''kitêbê''' vekir û dest bi xwendinê kir.}} #* {{J:Melayê Cizirî:Dîwan:2004|r=44|jêgirtin=Me ji ser çeşmeyê ḥeywan qedeḥek ṣafî vexwar<br>Nagihî lez̤z̤et û z̤ewqa me bi ṣed cildê '''kitab'''}} #* {{J:Feqiyê Teyran|sernav=Feqiyê Teyran jiyan berhem û helbestên wî|sala-weşandinê=2013|weşanxane=Nûbihar|çap=7|rûpel=130|amadekar=M. Xalid Sadinî|jêgirtin=Agir û pêta di dil da<br>Me„neya daxan ku hilda<br>Ew '''kitab''' naçit tu cilda<br>Hafîzê medhan im ez}} #* {{jêder-kitêb|ku|jêgirtin=We neẓertu fîl-kîtabî, yanî ez daxilê xanî bûm û min neẓer li '''kitêbê''' kir.|sernav=Tesrîfa Teremaxî|nivîskar={{w|Elî Teremaxî}}|r=64|amadekar=Aydın Üneşi|sal=~1600|sala weşandinê=2016|cih=Mêrdin}} #* {{jêder-kitêb|ku|jêgirtin=Ji şaîrê Kurmancan, bi zimanê Kurmancî, di tarîxa hezar û şeşsedî de di qeseba Bayezîdê de, hezretî Ehmedê Xanî '''kitêba''' ku telîf kiriye bi wezn bi nave Mem û Zînê, aşiq û maşûq, li weche muxtesr beyana wan dike.|sal=~1850|nivîskar={{w|Mele Mehmûdê Bazîdî}}|sernav=Mem û Zîn|sala weşandinê=2007|weşanxane=Lîs|r=23|amadekar=Xelîl Duhokî}} #* {{jêder-kitêb|ku|jêgirtin=Mirovek xwenda, alim hebî, nave wî "Ehmede Xanî" bî{{sic}}. Xwedê jê razî be, rehmeta Xwedê lê be, vî mirovî hin '''kitêbên''' Kurmancî nivîsîne.|sernav=Kurdistan|sal=1898|r=123|amadekar=M. Emîn Bozarslan|nivîskar={{w|Miqdad Midhet Bedirxan}}|sala weşandinê=1991|cild=1}} #* {{jêder|ku|jêgirtin=- Ma lê, ji te xeyidîme, ma çawan ji te naxeyidim. Te ez avêtim nav '''kitêb''' û kaxizan, te ez kirim hogir û hevala bermayên [[qaşûl]]ên dar û qirş û [[hevser]]a [[caw]] û [[potik]]ên [[zibilgeh]]ê.|''Gazinda Xencera Min, Hawar'', [[w:Celadet Alî Bedir-Xan|Celadet Alî Bedir-Xan]], hejmar 12}} #* {{J:Mem û Zîn:2004|rûpel=48|jêgirtin=Enwa'e milel xwidan'''kitêb''' in<br>Kirmanc-i tenê di bêhesêb in}} # Her kitêba [[miqeddes]] wekî [[Qur'an]] an [[Încîl]]. #* {{J:Încîl:1872:Sayim|jêgirtin=Îsa cewab da ji wan ṟa, û go: Ey! şaşxunan, ne '''kitêb''' dizanin û ne quwwetê Xodê|r=105}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|کتێب}} * {{ku-kr|к'ьтеб}} ==== Jê ==== {{kol3|ku|cure=Jê |kitêbdank |kitêbdost |kitêbdostî |kitêbfiroş |kitêbfiroşgeh |kitêbfiroşxane |kitêbgeh |kitêbhez |kitêbhezî |kitêbik |kitêbî |kitêbk |kitêbxane |kitêbxanevan |kitêbxanevanî |kitêbyar |kitêbyarî }} ==== Etîmolojî ==== {{root|ku|ar|ك ت ب}} Ji {{deyn|ar|ku|كِتَاب}} ji reha {{ar-reh|ك ت ب|nekat=1}} ''têkilî rêzkirinê û çêkirina rêzikan ji wê yekê jî têkilî nivîsînê'', ji {{mîr|sem-wes-pro|ar|*katab-|w=xurandin, xeritandin}}. Ev reh koka peyvin din jî ne weku: {{q|ku|katib}}, {{q|ku|mekteb}}, {{q|ku|ketîbe}}. ==== Bide ber ==== {{kol3|ku |belavok |defter |kovar |namilke |rojname }} ==== Bi zaravayên din ==== *{{Z|ckb}}: {{W|ckb|کتێب|tr=kitêb}} ==== Werger ==== {{werger-ser|koma kaxezan}} * {{Z|abq}}: {{W-|abq|книга}}, {{W-|abq|апхьага}}, {{W-|abq|кьтап}} * {{Z|ab}}: {{W-|ab|ашәҟәы}} * {{Z|ady}}: {{W-|ady|тхылъ}} * {{Z|aa}}: {{W-|aa|kitab}} * {{Z|af}}: {{W+|af|boek}} * {{Z|xag}}: {{W-|xag|𐕁𐔼𐕗}} * {{Z|akz}}: {{W-|akz|holisso}} * {{Z|sq}}: {{W+|sq|libër|n}} * {{Z|de}}: {{W+|de|Buch|nt}} *: {{Z|gsw}}: {{W-|gsw|Buech|nt}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Boch|nt}} *: {{Z|pdc}}: {{W-|pdc|Buch|nt}} * {{Z|alt}}: {{W-|alt|бичик}}, {{W-|alt|книга}} * {{Z|abs}}: {{W-|abs|buku}} * {{Z|am}}: {{W-|am|መጽሃፍ}} * Apaçî: *: {{Z|apw}}: {{W-|apw|nałtsoos}} * {{Z|an}}: {{W-|an|libro|n}} * {{Z|rup}}: {{W-|rup|vivlie}}, {{W-|rup|carte}} * {{Z|as}}: {{W-|as|কিতাপ}}, {{W-|as|পুথি}} * {{Z|ast}}: {{W+|ast|llibru|n}} * {{Z|tay}}: {{W-|tay|biru'}} * {{Z|aot}}: {{W-|aot|kitap}} * {{Z|av}}: {{W-|av|тӏехь}}, {{W-|av|таптар}}, {{W-|av|тӏахьал}} * {{Z|ay}}: {{W-|ay|panka}} * {{Z|ain}}: {{W-|ain|カㇺビソㇱ|tr=kambisosh}} * {{Z|az}}: {{W+|az|kitab}} * {{Z|bm}}: {{W-|bm|gafɛ}} * {{Z|eu}}: {{W+|eu|liburu}} * {{Z|ba}}: {{W-|ba|китап}} * {{Z|be}}: {{W+|be|кні́га|m}}, {{W-|be|кні́жка|m}} * {{Z|bn}}: {{W+|bn|বই}}, {{W+|bn|কিতাব}}, {{W+|bn|গ্রন্থ}}, {{W+|bn|পুস্তক}} * {{Z|bth}}: {{W-|bth|buk}} * {{Z|bi}}: {{W-|bi|buk}} * {{Z|br}}: {{W+|br|levr|n}} * {{Z|bg}}: {{W+|bg|кни́га|m}} * {{Z|my}}: {{W+|my|စာအုပ်}} * {{Z|bua}}: {{W-|bua|ном}} * {{Z|kac}}: {{W-|kac|laika buk}} * {{Z|ch}}: {{W-|ch|lepblo}} * {{Z|chg}}: {{W-|chg|كتاب|tr=kitab}} * {{Z|ce}}: {{W-|ce|кинишка}}, {{W-|ce|китаб}}, {{W-|ce|книга}}, {{W-|ce|книшка}}, {{W-|ce|кинчка}}, {{W-|ce|жайна}} * {{Z|cs}}: {{W+|cs|kniha|m}} * {{Z|chr}}: {{W-|chr|ᏗᎪᏪᎵ}}, {{W+|chr|ᎪᏪᎵ}} * {{Z|chy}}: {{W-|chy|mȯxe'ėstoo'e}} * {{Z|ny}}: {{W-|ny|buku}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|書}} *: {{Z|dng}}: {{W-|dng|фу}} *: {{Z|gan}}: {{W-|gan|書}} *: {{Z|hak}}: {{W-|hak|書|tr=sû}} *: {{Z|cjy}}: {{W-|cjy|書}} *: {{Z|cmn}}: {{W+|cmn|書}} *: {{Z|mnp}}: {{W-|mnp|書}} *: {{Z|cdo}}: {{W-|cdo|書}} *: {{Z|nan}}: {{W+|nan|冊|tr=chheh}}, {{W+|nan|書|tr=chu}} *: {{Z|wuu}}: {{W-|wuu|書}} *: {{Z|hsn}}: {{W-|hsn|書}} * {{Z|cv}}: {{W-|cv|кӗнеке}} * {{Z|dlm}}: {{W-|dlm|lebro|n}} * {{Z|da}}: {{W+|da|bog|g}} * {{Z|dv}}: {{W-|dv|ފޮތް}} * {{Z|dtp}}: {{W-|dtp|buuk}} * {{Z|ovd}}: {{W-|ovd|buok|m}} * {{Z|id}}: {{W+|id|buku}}, {{W+|id|kitab}} * {{Z|ar}}: {{W+|ar|كِتَاب|n}} *: {{Z|arq}}: {{W-|arq|كتاب|n|tr=ktāb}} *: {{Z|arz}}: {{W-|arz|كتاب|n|tr=ketāb}} *: {{Z|acm}}: {{W-|acm|كِتَاب|n}} *: {{Z|ary}}: {{W-|ary|كتاب|n|tr=ktāb}} *: {{Z|apc}}: {{W-|apc|كتاب|tr=ktāb, ktēb}} *: {{Z|aeb}}: {{W-|aeb|كتاب|n|tr=ktēb}} * {{Z|hy}}: {{W+|hy|գիրք}} * {{Z|myv}}: {{W-|myv|конёвкс}}, {{W-|myv|кинига}} * {{Z|eo}}: {{W+|eo|libro}} * {{Z|et}}: {{W+|et|raamat}} * {{Z|gez}}: {{W-|gez|መጽሐፍ}} * {{Z|evn}}: {{W-|evn|книга}} * {{Z|ee}}: {{W-|ee|agbalẽ}} * {{Z|ext}}: {{W-|ext|llibru|n}} * {{Z|fax}}: {{W-|fax|libru|n}} * {{Z|fa}}: {{W+|fa|کِتاب|tr=ketâb}}, {{W+|fa|نَسک|tr=nask}}, {{W+|fa|نامِه|tr=nâme}} * {{Z|fo}}: {{W+|fo|bók|m}} * {{Z|fj}}: {{W+|fj|vola}}, {{W-|fj|ivola}} * {{Z|fi}}: {{W+|fi|kirja}} * {{Z|fr}}: {{W+|fr|livre|n}}, {{W+|fr|bouquin|n}} * {{Z|fur}}: {{W-|fur|libri|n}} * {{Z|frr}}: {{W-|frr|bök|nt}}, {{W-|frr|buk|nt}} * {{Z|stq}}: {{W-|stq|Bouk|nt}} * {{Z|fy}}: {{W+|fy|boek|nt}} * {{Z|ff}}: *: Adlamî: {{W-|ff|𞤣𞤫𞤬𞤼𞤫𞤪𞤫}} *: Latînî: {{W-|ff|deftere}} * {{Z|gd}}: {{W+|gd|leabhar|n}} * {{Z|gag}}: {{W-|gag|kitap}} * {{Z|gl}}: {{W+|gl|libro|n}} * {{Z|glk}}: {{W-|glk|کیتاب|tr=kitāb}} * {{Z|got}}: {{W-|got|𐌱𐍉𐌺𐍉𐍃|m-p}} * {{Z|gu}}: {{W+|gu|પુસ્તક|m}}, {{W-|gu|ચોપડી}} * {{Z|ka}}: {{W+|ka|წიგნი}} * {{Z|gn}}: {{W+|gn|kuatiañe'ẽ}}, {{W-|gn|[[aranduka]]}} * {{Z|ht}}: {{W-|ht|liv}} * {{Z|haw}}: {{W-|haw|puke}}, {{W-|haw|liwele}} * {{Z|ha}}: {{W+|ha|littafi}} * {{Z|hi}}: {{W+|hi|पुस्तक|m}}, {{W+|hi|किताब|m}}, {{W+|hi|बुक|m}}, {{W+|hi|ग्रंथ|n}}, {{W+|hi|बही|m}}, {{W+|hi|पोथी|m}}, {{W+|hi|पोथा|n}}, {{W+|hi|पुस्तिका|m}}, {{W+|hi|सिफर}} * {{Z|hil}}: {{W-|hil|tulún-an}} * {{Z|meu}}: {{W-|meu|buka}} * {{Z|hnj}}: {{W-|hnj|phoo}}, {{W-|hnj|phoo ntawv}} * {{Z|mww}}: {{W-|mww|ntawv}} * {{Z|nl}}: {{W+|nl|boek|nt}} * {{Z|hrx}}: {{W-|hrx|Buch|nt}} * {{Z|tts}}: {{W-|tts|ปึ้ง|tr=pụ̂ng}} * {{Z|iba}}: {{W-|iba|surat}}, {{W-|iba|bup}} * {{Z|he}}: {{W+|he|סֵפֶר|n|tr=séfer}} * {{Z|io}}: {{W+|io|libro}} * {{Z|ig}}: {{W-|ig|akwụkwọ}} * {{Z|ang}}: {{W-|ang|bōc|m}} * {{Z|enm}}: {{W-|enm|bok}} * {{Z|en}}: {{W+|en|book}} * {{Z|izh}}: {{W-|izh|kirja}} * {{Z|inh}}: {{W-|inh|китаб}} * {{Z|ia}}: {{W+|ia|libro}} * {{Z|iu}}: {{W+|iu|ᕿᒥᕐᕈᐊᑦ}} *: {{Z|iu}}: {{W-|iu|unikkausik}} * {{Z|sga}}: {{W-|sga|lebor|n}} * {{Z|ga}}: {{W+|ga|leabhar|n}} * {{Z|ist}}: {{W-|ist|leîbro|n}} * {{Z|it}}: {{W+|it|libro|n}} * {{Z|is}}: {{W+|is|bók|m}} * {{Z|ja}}: {{W+|ja|本|tr=ほん, hon}}, {{W+|ja|書籍|tr=しょせき, shoseki}}, {{W+|ja|ブック|tr=bukku}} * {{Z|kaw}}: {{W-|kaw|tulis}} * {{Z|jv}}: {{W+|jv|buku}}, {{W+|jv|layang}}, {{W-|jv|serat}} * {{Z|kbd}}: {{W-|kbd|тхылъ}} * {{Z|kab}}: {{W-|kab|adlis}} * {{Z|kl}}: {{W-|kl|atuagaq}} * {{Z|xal}}: {{W-|xal|дегтр}} * {{Z|kn}}: {{W+|kn|ಪುಸ್ತಕ}} * {{Z|krc}}: {{W-|krc|китап}} * {{Z|kaa}}: {{W-|kaa|kitap}} * {{Z|krl}}: {{W-|krl|kirju}} * {{Z|csb}}: {{W-|csb|knéga|m}}, {{W-|csb|knyga|m}}, {{W-|csb|knëga|m}}, {{W-|csb|ksążka|m}} * {{Z|ca}}: {{W+|ca|llibre|n}} * {{Z|qu}}: {{W+|qu|liwru}}, {{W+|qu|p'anqa}} * {{Z|ky}}: {{W+|ky|китеп}} * {{Z|kg}}: {{W-|kg|dibuku}} * {{Z|ki}}: {{W-|ki|rifuku}} * {{Z|si}}: {{W+|si|පොත}} * {{Z|rw}}: {{W-|rw|igitabo|c7|c8}} * {{Z|gil}}: {{W-|gil|boki}} * {{Z|kis}}: {{W-|kis|egetabu}} * {{Z|kpv}}: {{W-|kpv|небӧг}}, {{W-|kpv|книга}} * {{Z|kok}}: {{W-|kok|पुस्तक}} * {{Z|ko}}: {{W-|ko|책(冊)}}, {{W-|ko|도서(圖書)}} * {{Z|kw}}: {{W-|kw|lyver|n}} * {{Z|co}}: {{W+|co|libru|n}} * {{Z|lou}}: {{W-|lou|liv}} * {{Z|mfe}}: {{W-|mfe|liv}} * {{Z|crs}}: {{W-|crs|liv}} * {{Z|kum}}: {{W-|kum|китап}} * {{Z|fkv}}: {{W-|fkv|kirja}} * {{Z|kj}}: {{W-|kj|embo}} * {{Z|lad}}: *: Îbranî: {{W-|lad|ליב׳רו|n}} *: Latînî: {{W-|lad|livro|n}} * {{Z|lbe}}: {{W-|lbe|лу}} * {{Z|lkt}}: {{W-|lkt|wówapi}} * {{Z|la}}: {{W+|la|liber|n}}, {{W-|la|caudex|n}} * {{Z|lv}}: {{W+|lv|grāmata|m}} * {{Z|lo}}: {{W+|lo|ປຶ້ມ}}, {{W+|lo|ປຶ້ມຂຽນ}}, {{W-|lo|ຫນັງສື}}, {{W-|lo|ສັດຖະ}}, {{W-|lo|ພັບ}} * {{Z|lzz}}: {{W-|lzz|სუპარა}} * {{Z|lez}}: {{W-|lez|улуб}}, {{W-|lez|ктаб}}, {{W-|lez|дафтар}} * {{Z|mhx}}: {{W-|mhx|mug sug' paug'}}, {{W-|mhx|tung" paug'}}, {{W-|mhx|paug'}} * {{Z|ln}}: {{W-|ln|búku|c9a|c10a}} * {{Z|lij}}: {{W-|lij|lìbbro|n}}, {{W-|lij|libbro}} * {{Z|li}}: {{W+|li|book|m}} * {{Z|lt}}: {{W+|lt|knyga|m}} * {{Z|liv}}: {{W-|liv|rōntõz}} * {{Z|lmo}}: {{W-|lmo|liber}} * {{Z|lg}}: {{W-|lg|ekitabo}} * {{Z|luy}}: {{W-|luy|sitabu}} * {{Z|lb}}: {{W+|lb|Buch|nt}} * {{Z|mk}}: {{W+|mk|книга|m}} * {{Z|mg}}: {{W+|mg|boky}} * {{Z|ml}}: {{W+|ml|പുസ്തകം}} * {{Z|pqm}}: {{W-|pqm|wikhikon}} * {{Z|ms}}: {{W+|ms|buku}}, {{W+|ms|kitab}}, {{W+|ms|pustaka}} * {{Z|mt}}: {{W+|mt|ktieb|n}} * {{Z|mnc}}: {{W-|mnc|ᠪᡳᡨᡥᡝ}}, {{W-|mnc|ᠴᠠᡤᠠᠨ}}, {{W-|mnc|ᠨᠣᠮᡠᠨ}} * {{Z|gv}}: {{W-|gv|lioar|n}} * {{Z|mns-nor}}: {{W-|mns-nor|кнӣга}} * {{Z|mi}}: {{W+|mi|pukapuka}} * {{Z|mr}}: {{W+|mr|पुस्तक|m}} * {{Z|mhr}}: {{W-|mhr|книга}} * {{Z|mrc}}: {{W-|mrc|onyor}} * {{Z|yua}}: {{W-|yua|juʼun}} * {{Z|hu}}: {{W+|hu|könyv}} * {{Z|xmf}}: {{W-|xmf|სუფარა|n}}, {{W-|xmf|წინგი}} * {{Z|egy}}: {{W-egy|mḏꜣt|m|h=Y1:t*Z1-V12:Z1}}, {{W-egy|šfdw|n|h=S:f-d-w-V12}} * {{Z|mvi}}: {{W-|mvi|書物|tr=すぃむくㇲ, simuks}} * {{Z|mwl}}: {{W-|mwl|lhibro|n}} * {{Z|mdf}}: {{W-|mdf|книга}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|ном}}, {{W+|mn|бичиг}} *: Mongolî: {{W-|mn|ᠨᠣᠮ}}, {{W-|mn|ᠪᠢᠴᠢᠭ᠋}} * {{Z|mnw}}: {{W-|mnw|လိက် အုပ်|tr=lòik up}} * {{Z|wmw}}: {{W-|wmw|kitabu}}, {{W-|wmw|buku}}, {{W-|wmw|livro}} * {{Z|nah}}: {{W+|nah|amoxtli}} *: {{Z|nci}}: {{W-|nci|āmoxtli}} * {{Z|gld}}: {{W-|gld|дангса}} * {{Z|nap}}: {{W-|nap|lìbbro|n}} * {{Z|nv}}: {{W-|nv|naaltsoos}} * {{Z|nds}}: *: {{Z|nds-nl}}: {{W-|nds-nl|book|nt}} *: {{Z|nds-de}}: {{W-|nds-de|Book|nt}} * {{Z|yrk}}: {{W-|yrk|книга}}, {{W-|yrk|толаӈгобць’}} * {{Z|ne}}: {{W-|ne|पुस्तक}}, {{W+|ne|किताप}} * {{Z|new}}: {{W-|new|सफू}} * {{Z|niv}}: {{W-|niv|питғы}} * {{Z|nog}}: {{W-|nog|китап}} * {{Z|no}}: *: {{Z|no}}: {{W+|no|bok|n|m}} *: {{Z|nn}}: {{W+|nn|bok|m}} * {{Z|ood}}: {{W-|ood|ʼoʼohana}} * {{Z|ojw}}: {{W-|ojw|masinahikan}} * {{Z|oj}}: {{W-|oj|mazina'igan}} * {{Z|ryu}}: {{W-|ryu|書物|tr=すむち, sumuchi, しむち, shimuchi}} * {{Z|pro}}: {{W-|pro|libre}} * {{Z|oc}}: {{W+|oc|libre|n}} * {{Z|or}}: {{W+|or|ବହି}} * {{Z|oaa}}: {{W-|oaa|бичихэ}} * {{Z|os}}: {{W-|os|чиныг}} * {{Z|ota}}: {{W-|ota|كتاب|tr=kitâb}} * {{Z|ug}}: {{W+|ug|كىتاب}} * {{Z|uz}}: {{W+|uz|kitob}} * {{Z|pi}}: {{W-|pi|potthaka}} *: {{Z|pi}}: {{W-|pi|पोत्थक}} *: {{Z|pi}}: {{W-|pi|โปตถะกะ}} * {{Z|pap}}: {{W-|pap|buki}} * {{Z|paw}}: {{W-|paw|raáwihaakaraaʾit}}, {{W-|paw|raáwihaakaraaʾiitusuʾ}} * {{Z|ps}}: {{W+|ps|کتاب|n|tr=ketāb}} * {{Z|pms}}: {{W-|pms|lìber}} * {{Z|pdt}}: {{W-|pdt|Buak|nt}} * {{Z|pox}}: {{W-|pox|bükvoi|p}} * {{Z|pl}}: {{W+|pl|książka|m}}, {{W+|pl|księga|m}} * {{Z|pt}}: {{W+|pt|livro|n}} * {{Z|prg}}: {{W-|prg|lāiskas|n}} * {{Z|pkp}}: {{W-|pkp|lau}}, {{W-|pkp|puka}} * Puncabî: *: Şaxmuxî: {{W+|pa|پستک|n}}, {{W+|pa|کتاب|m|tr=ktāb}} *: Gurmuxî: {{W-|pa|ਪੁਸਤਕ|n}}, {{W-|pa|ਕਿਤਾਬ}} * {{Z|kk}}: {{W+|kk|кітап}} *: {{Z|kk}}: {{W-|kk|كىتاپ}} * {{Z|cop}}: {{W-|cop|ϫⲱⲙ|n}} * {{Z|rah}}: {{W-|rah|কাওছা|tr=káosa}} * {{Z|mwr}}: {{W-|mwr|पोथी|tr=pothī|m}} * {{Z|rgn}}: {{W-|rgn|lìvar|n}} * {{Z|rm}}: {{W-|rm|cudesch}} * {{Z|rom}}: {{W-|rom|ginadyi|m}} * {{Z|ro}}: {{W+|ro|carte|m}} * {{Z|ru}}: {{W+|ru|кни́га|m}}, {{W+|ru|кни́жка|m}} * {{Z|rue}}: {{W-|rue|кни́га|m}} * {{Z|se}}: {{W-|se|girji}} * {{Z|sma}}: {{W-|sma|gærja}} * {{Z|smn}}: {{W-|smn|kirje}} * {{Z|sjd}}: {{W-|sjd|кыррьй}}, {{W-|sjd|кнӣга}} * {{Z|smj}}: {{W-|smj|girjje}} * {{Z|sms}}: {{W-|sms|ǩeʹrjj}} * {{Z|sgs}}: {{W-|sgs|kninga|m}} * {{Z|sa}}: {{W+|sa|पुस्तक|nt}}, {{W+|sa|ग्रन्थ|nt}} * {{Z|scn}}: {{W+|scn|libbru|n}} * {{Z|sky}}: {{W-|sky|laumea}} * {{Z|szl}}: {{W-|szl|kniga|m}} * {{Z|sd}}: {{W+|sd|ڪتاب|n|tr=kitāb|cuda=ڪِتابُ}} * {{Z|srn}}: {{W-|srn|buku}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|књи̏га|m}} *: Latînî: {{W+|sh|knjȉga|m}} * {{Z|syc}}: {{W-|syc|ܟܬܒܐ|n|tr=kṯāḇā}} * {{Z|syl}}: {{W-|syl|ꠛꠂ}} * {{Z|sco}}: {{W-|sco|beuk}} * {{Z|cu}}: *: Kirîlî: {{W-|cu|боукꙑ|m}}, {{W-|cu|кънигꙑ|m-p}} * {{Z|orv}}: {{W-|orv|кънига|m}} * {{Z|sk}}: {{W+|sk|kniha|m}} * {{Z|sl}}: {{W+|sl|knjíga|m}} * {{Z|zlw-slv}}: {{W-|zlw-slv|knega|m}} * {{Z|so}}: {{W+|so|buug|n}}, {{W-|so|kitaab|n}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|knigły|m-p}} *: {{Z|hsb}}: {{W-|hsb|kniha|m}} * {{Z|st}}: {{W+|st|buka}} * {{Z|es}}: {{W+|es|libro|n}} * {{Z|su}}: {{W-|su|ᮘᮥᮊᮥ}} * {{Z|xsv}}: {{W-|xsv|laiskas|n}} * {{Z|sva}}: {{W-|sva|ლა̈ირ}} * {{Z|sw}}: {{W+|sw|kitabu}}, {{W+|sw|vitabu|p}} * {{Z|ss}}: {{W-|ss|íncwadzí|c9|c10}} * {{Z|sv}}: {{W+|sv|bok|g}} * {{Z|shn}}: {{W-|shn|ပပ်ႉ}}, {{W-|shn|ၸႃႇဢုၵ်ႉ}} * {{Z|sn}}: {{W-|sn|bhuku}} * {{Z|cjs}}: {{W-|cjs|ном|tr=nom}}, {{W-|cjs|книга}} * {{Z|tab}}: {{W-|tab|китаб}} * {{Z|tg}}: {{W+|tg|китоб}} * {{Z|tl}}: {{W+|tl|libro}}, {{W+|tl|aklat}} * {{Z|ta}}: {{W+|ta|நூல்}}, {{W+|ta|புத்தகம்}} * {{Z|roa-tar}}: {{W-|roa-tar|libbre|n}} * {{Z|shi}}: {{W-|shi|ⴰⵔⵔⴰ|n}} * {{Z|th}}: {{W+|th|หนังสือ}}, {{W+|th|สมุด}} * {{Z|te}}: {{W+|te|పుస్తకం}}, {{W-|te|పొత్తం}} * {{Z|crh}}: {{W-|crh|kitap}} * {{Z|tt}}: {{W+|tt|китап}} * {{Z|tet}}: {{W-|tet|livru}} * {{Z|tig}}: {{W-|tig|ክታብ}} * {{Z|ti}}: {{W-|ti|መጽሓፍ}}, {{W-|ti|መጽሐፍ}} * {{Z|otk}}: {{W-|otk|𐰋𐰃𐱅𐰏}} * {{Z|tr}}: {{W+|tr|kitap}}, {{W+|tr|betik}} * {{Z|tk}}: {{W-|tk|kitap}} * {{Z|bo}}: {{W-|bo|དེབ}}, {{W-|bo|ཕྱག་དེབ}} * {{Z|tli}}: {{W-|tli|x’úx’}} * {{Z|tpi}}: {{W-|tpi|buk}} * {{Z|txb}}: {{W-|txb|postak}} * {{Z|tn}}: {{W+|tn|buka}} * {{Z|tum}}: {{W-|tum|buku}} * {{Z|tvl}}: {{W-|tvl|tusi}} * {{Z|tyv}}: {{W-|tyv|ном}} * {{Z|udi}}: {{W-|udi|ҝирк}} * {{Z|udm}}: {{W-|udm|книга}} * {{Z|unm}}: {{W-|unm|lekhikàn}} * {{Z|ur}}: {{W+|ur|کِتاب|m|tr=kitāb}}, {{W-|ur|پُسْتَک|m|tr=pustak}}, {{W-|ur|بُک|m|tr=buk}} * {{Z|urh}}: {{W-|urh|e̖be}} * {{Z|uk}}: {{W-|uk|кни́жка|m}}, {{W+|uk|кни́га|m}} * {{Z|vec}}: {{W-|vec|łìbro|n}} * {{Z|vep}}: {{W-|vep|kirj}} * {{Z|vi}}: {{W+|vi|sách}}, {{W+|vi|sổ}}, {{W+|vi|sách giáo khoa}} * {{Z|vo}}: {{W+|vo|buk}} * {{Z|vot}}: {{W-|vot|tširjõ}} * {{Z|wa}}: {{W+|wa|live|n}} * {{Z|war}}: {{W-|war|basahon}}, {{W-|war|barasahon}} * {{Z|cy}}: {{W+|cy|llyfr|n}} * {{Z|wrh}}: {{W-|wrh|garrandarang}} * {{Z|wym}}: {{W-|wym|bihła|nt}}, {{W-|wym|büch}} * {{Z|wo}}: {{W-|wo|[[tééré]] bi}}, {{W+|wo|téere}} * {{Z|wuh}}: {{W-|wuh|huaiqa}} * {{Z|kjh}}: {{W-|kjh|кинде}} * {{Z|km}}: {{W+|km|សៀវភៅ}} * {{Z|xh}}: {{W-|xh|incwadi|c9|c10}} * {{Z|yai}}: {{W-|yai|китоб}} * {{Z|sah}}: {{W-|sah|кинигэ}} * {{Z|tao}}: {{W-|tao|vakong}} * {{Z|yi}}: {{W-|yi|בוך|nt}}, {{W-|yi|ספֿר|n|tr=seyfer}}, {{W-|yi|חיבור|n|tr=khiber}} * {{Z|yo}}: {{W-|yo|ìwé}} * {{Z|el}}: {{W+|el|βιβλίο|nt}}, {{W+|el|τόμος|n}} *: Kevn: {{W-|grc|βιβλίον|nt}} * {{Z|za}}: {{W-|za|saw}} * {{Z|zu}}: {{W+|zu|ibhuku|c5|c6}}, {{W+|zu|incwadi|c9|c10}} {{werger-bin}} :{{werger çavkanî|en|book|oldid=75472768|beş=Ev qismê Wergerê}} qfbz8krhf3evea0d67o4yxx4ldsjbpz 6347276 6347275 2026-08-30T22:09:47Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347276 wikitext text/x-wiki {{bnr-h|kiteb|Kitêb}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA|k(h)itêb}} * {{deng|ku|LL-Q36163 (kmr)-Ebulfîda-kitêb.wav|dever=Bidlîs}} * {{ku-kîte}} === Navdêr === [[Wêne:Latin_dictionary.jpg|thumb|Kitêb]] {{navdêr|ku|z=m}} # [[kom|Komeke]] [[kaxez]]ên bi [[nivîs]] û / yan [[resm]] yên di nav [[berg]]ekî de hatine [[çap]]kirin. #: {{hevmane|ku|pirtûk}} #: {{mk|ku|Wê rûpela 50 ya '''kitêbê''' vekir û dest bi xwendinê kir.}} #* {{jêder-kitêb|ku|jêgirtin=We neẓertu fîl-kîtabî, yanî ez daxilê xanî bûm û min neẓer li '''kitêbê''' kir.|sernav=Tesrîfa Teremaxî|nivîskar={{w|Elî Teremaxî}}|r=64|amadekar=Aydın Üneşi|sal=~1600|sala weşandinê=2016|cih=Mêrdin}} #* {{J:Feqiyê Teyran|sernav=Feqiyê Teyran jiyan berhem û helbestên wî|sala-weşandinê=2013|weşanxane=Nûbihar|çap=7|rûpel=130|amadekar=M. Xalid Sadinî|jêgirtin=Agir û pêta di dil da<br>Me„neya daxan ku hilda<br>Ew '''kitab''' naçit tu cilda<br>Hafîzê medhan im ez}} #* {{J:Melayê Cizirî:Dîwan:2004|r=44|jêgirtin=Me ji ser çeşmeyê ḥeywan qedeḥek ṣafî vexwar<br>Nagihî lez̤z̤et û z̤ewqa me bi ṣed cildê '''kitab'''}} #* {{J:Mem û Zîn:2004|rûpel=48|jêgirtin=Enwa'e milel xwidan'''kitêb''' in<br>Kirmanc-i tenê di bêhesêb in}} #* {{jêder-kitêb|ku|jêgirtin=Ji şaîrê Kurmancan, bi zimanê Kurmancî, di tarîxa hezar û şeşsedî de di qeseba Bayezîdê de, hezretî Ehmedê Xanî '''kitêba''' ku telîf kiriye bi wezn bi nave Mem û Zînê, aşiq û maşûq, li weche muxtesr beyana wan dike.|sal=~1850|nivîskar={{w|Mele Mehmûdê Bazîdî}}|sernav=Mem û Zîn|sala weşandinê=2007|weşanxane=Lîs|r=23|amadekar=Xelîl Duhokî}} #* {{jêder-kitêb|ku|jêgirtin=Mirovek xwenda, alim hebî, nave wî "Ehmede Xanî" bî{{sic}}. Xwedê jê razî be, rehmeta Xwedê lê be, vî mirovî hin '''kitêbên''' Kurmancî nivîsîne.|sernav=Kurdistan|sal=1898|r=123|amadekar=M. Emîn Bozarslan|nivîskar={{w|Miqdad Midhet Bedirxan}}|sala weşandinê=1991|cild=1}} #* {{jêder|ku|jêgirtin=- Ma lê, ji te xeyidîme, ma çawan ji te naxeyidim. Te ez avêtim nav '''kitêb''' û kaxizan, te ez kirim hogir û hevala bermayên [[qaşûl]]ên dar û qirş û [[hevser]]a [[caw]] û [[potik]]ên [[zibilgeh]]ê.|''Gazinda Xencera Min, Hawar'', [[w:Celadet Alî Bedir-Xan|Celadet Alî Bedir-Xan]], hejmar 12}} # Her kitêba [[miqeddes]] wekî [[Qur'an]] an [[Încîl]]. #* {{J:Încîl:1872:Sayim|jêgirtin=Îsa cewab da ji wan ṟa, û go: Ey! şaşxunan, ne '''kitêb''' dizanin û ne quwwetê Xodê|r=105}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|کتێب}} * {{ku-kr|к'ьтеб}} ==== Jê ==== {{kol3|ku|cure=Jê |kitêbdank |kitêbdost |kitêbdostî |kitêbfiroş |kitêbfiroşgeh |kitêbfiroşxane |kitêbgeh |kitêbhez |kitêbhezî |kitêbik |kitêbî |kitêbk |kitêbxane |kitêbxanevan |kitêbxanevanî |kitêbyar |kitêbyarî }} ==== Etîmolojî ==== {{root|ku|ar|ك ت ب}} Ji {{deyn|ar|ku|كِتَاب}} ji reha {{ar-reh|ك ت ب|nekat=1}} ''têkilî rêzkirinê û çêkirina rêzikan ji wê yekê jî têkilî nivîsînê'', ji {{mîr|sem-wes-pro|ar|*katab-|w=xurandin, xeritandin}}. Ev reh koka peyvin din jî ne weku: {{q|ku|katib}}, {{q|ku|mekteb}}, {{q|ku|ketîbe}}. ==== Bide ber ==== {{kol3|ku |belavok |defter |kovar |namilke |rojname }} ==== Bi zaravayên din ==== *{{Z|ckb}}: {{W|ckb|کتێب|tr=kitêb}} ==== Werger ==== {{werger-ser|koma kaxezan}} * {{Z|abq}}: {{W-|abq|книга}}, {{W-|abq|апхьага}}, {{W-|abq|кьтап}} * {{Z|ab}}: {{W-|ab|ашәҟәы}} * {{Z|ady}}: {{W-|ady|тхылъ}} * {{Z|aa}}: {{W-|aa|kitab}} * {{Z|af}}: {{W+|af|boek}} * {{Z|xag}}: {{W-|xag|𐕁𐔼𐕗}} * {{Z|akz}}: {{W-|akz|holisso}} * {{Z|sq}}: {{W+|sq|libër|n}} * {{Z|de}}: {{W+|de|Buch|nt}} *: {{Z|gsw}}: {{W-|gsw|Buech|nt}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Boch|nt}} *: {{Z|pdc}}: {{W-|pdc|Buch|nt}} * {{Z|alt}}: {{W-|alt|бичик}}, {{W-|alt|книга}} * {{Z|abs}}: {{W-|abs|buku}} * {{Z|am}}: {{W-|am|መጽሃፍ}} * Apaçî: *: {{Z|apw}}: {{W-|apw|nałtsoos}} * {{Z|an}}: {{W-|an|libro|n}} * {{Z|rup}}: {{W-|rup|vivlie}}, {{W-|rup|carte}} * {{Z|as}}: {{W-|as|কিতাপ}}, {{W-|as|পুথি}} * {{Z|ast}}: {{W+|ast|llibru|n}} * {{Z|tay}}: {{W-|tay|biru'}} * {{Z|aot}}: {{W-|aot|kitap}} * {{Z|av}}: {{W-|av|тӏехь}}, {{W-|av|таптар}}, {{W-|av|тӏахьал}} * {{Z|ay}}: {{W-|ay|panka}} * {{Z|ain}}: {{W-|ain|カㇺビソㇱ|tr=kambisosh}} * {{Z|az}}: {{W+|az|kitab}} * {{Z|bm}}: {{W-|bm|gafɛ}} * {{Z|eu}}: {{W+|eu|liburu}} * {{Z|ba}}: {{W-|ba|китап}} * {{Z|be}}: {{W+|be|кні́га|m}}, {{W-|be|кні́жка|m}} * {{Z|bn}}: {{W+|bn|বই}}, {{W+|bn|কিতাব}}, {{W+|bn|গ্রন্থ}}, {{W+|bn|পুস্তক}} * {{Z|bth}}: {{W-|bth|buk}} * {{Z|bi}}: {{W-|bi|buk}} * {{Z|br}}: {{W+|br|levr|n}} * {{Z|bg}}: {{W+|bg|кни́га|m}} * {{Z|my}}: {{W+|my|စာအုပ်}} * {{Z|bua}}: {{W-|bua|ном}} * {{Z|kac}}: {{W-|kac|laika buk}} * {{Z|ch}}: {{W-|ch|lepblo}} * {{Z|chg}}: {{W-|chg|كتاب|tr=kitab}} * {{Z|ce}}: {{W-|ce|кинишка}}, {{W-|ce|китаб}}, {{W-|ce|книга}}, {{W-|ce|книшка}}, {{W-|ce|кинчка}}, {{W-|ce|жайна}} * {{Z|cs}}: {{W+|cs|kniha|m}} * {{Z|chr}}: {{W-|chr|ᏗᎪᏪᎵ}}, {{W+|chr|ᎪᏪᎵ}} * {{Z|chy}}: {{W-|chy|mȯxe'ėstoo'e}} * {{Z|ny}}: {{W-|ny|buku}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|書}} *: {{Z|dng}}: {{W-|dng|фу}} *: {{Z|gan}}: {{W-|gan|書}} *: {{Z|hak}}: {{W-|hak|書|tr=sû}} *: {{Z|cjy}}: {{W-|cjy|書}} *: {{Z|cmn}}: {{W+|cmn|書}} *: {{Z|mnp}}: {{W-|mnp|書}} *: {{Z|cdo}}: {{W-|cdo|書}} *: {{Z|nan}}: {{W+|nan|冊|tr=chheh}}, {{W+|nan|書|tr=chu}} *: {{Z|wuu}}: {{W-|wuu|書}} *: {{Z|hsn}}: {{W-|hsn|書}} * {{Z|cv}}: {{W-|cv|кӗнеке}} * {{Z|dlm}}: {{W-|dlm|lebro|n}} * {{Z|da}}: {{W+|da|bog|g}} * {{Z|dv}}: {{W-|dv|ފޮތް}} * {{Z|dtp}}: {{W-|dtp|buuk}} * {{Z|ovd}}: {{W-|ovd|buok|m}} * {{Z|id}}: {{W+|id|buku}}, {{W+|id|kitab}} * {{Z|ar}}: {{W+|ar|كِتَاب|n}} *: {{Z|arq}}: {{W-|arq|كتاب|n|tr=ktāb}} *: {{Z|arz}}: {{W-|arz|كتاب|n|tr=ketāb}} *: {{Z|acm}}: {{W-|acm|كِتَاب|n}} *: {{Z|ary}}: {{W-|ary|كتاب|n|tr=ktāb}} *: {{Z|apc}}: {{W-|apc|كتاب|tr=ktāb, ktēb}} *: {{Z|aeb}}: {{W-|aeb|كتاب|n|tr=ktēb}} * {{Z|hy}}: {{W+|hy|գիրք}} * {{Z|myv}}: {{W-|myv|конёвкс}}, {{W-|myv|кинига}} * {{Z|eo}}: {{W+|eo|libro}} * {{Z|et}}: {{W+|et|raamat}} * {{Z|gez}}: {{W-|gez|መጽሐፍ}} * {{Z|evn}}: {{W-|evn|книга}} * {{Z|ee}}: {{W-|ee|agbalẽ}} * {{Z|ext}}: {{W-|ext|llibru|n}} * {{Z|fax}}: {{W-|fax|libru|n}} * {{Z|fa}}: {{W+|fa|کِتاب|tr=ketâb}}, {{W+|fa|نَسک|tr=nask}}, {{W+|fa|نامِه|tr=nâme}} * {{Z|fo}}: {{W+|fo|bók|m}} * {{Z|fj}}: {{W+|fj|vola}}, {{W-|fj|ivola}} * {{Z|fi}}: {{W+|fi|kirja}} * {{Z|fr}}: {{W+|fr|livre|n}}, {{W+|fr|bouquin|n}} * {{Z|fur}}: {{W-|fur|libri|n}} * {{Z|frr}}: {{W-|frr|bök|nt}}, {{W-|frr|buk|nt}} * {{Z|stq}}: {{W-|stq|Bouk|nt}} * {{Z|fy}}: {{W+|fy|boek|nt}} * {{Z|ff}}: *: Adlamî: {{W-|ff|𞤣𞤫𞤬𞤼𞤫𞤪𞤫}} *: Latînî: {{W-|ff|deftere}} * {{Z|gd}}: {{W+|gd|leabhar|n}} * {{Z|gag}}: {{W-|gag|kitap}} * {{Z|gl}}: {{W+|gl|libro|n}} * {{Z|glk}}: {{W-|glk|کیتاب|tr=kitāb}} * {{Z|got}}: {{W-|got|𐌱𐍉𐌺𐍉𐍃|m-p}} * {{Z|gu}}: {{W+|gu|પુસ્તક|m}}, {{W-|gu|ચોપડી}} * {{Z|ka}}: {{W+|ka|წიგნი}} * {{Z|gn}}: {{W+|gn|kuatiañe'ẽ}}, {{W-|gn|[[aranduka]]}} * {{Z|ht}}: {{W-|ht|liv}} * {{Z|haw}}: {{W-|haw|puke}}, {{W-|haw|liwele}} * {{Z|ha}}: {{W+|ha|littafi}} * {{Z|hi}}: {{W+|hi|पुस्तक|m}}, {{W+|hi|किताब|m}}, {{W+|hi|बुक|m}}, {{W+|hi|ग्रंथ|n}}, {{W+|hi|बही|m}}, {{W+|hi|पोथी|m}}, {{W+|hi|पोथा|n}}, {{W+|hi|पुस्तिका|m}}, {{W+|hi|सिफर}} * {{Z|hil}}: {{W-|hil|tulún-an}} * {{Z|meu}}: {{W-|meu|buka}} * {{Z|hnj}}: {{W-|hnj|phoo}}, {{W-|hnj|phoo ntawv}} * {{Z|mww}}: {{W-|mww|ntawv}} * {{Z|nl}}: {{W+|nl|boek|nt}} * {{Z|hrx}}: {{W-|hrx|Buch|nt}} * {{Z|tts}}: {{W-|tts|ปึ้ง|tr=pụ̂ng}} * {{Z|iba}}: {{W-|iba|surat}}, {{W-|iba|bup}} * {{Z|he}}: {{W+|he|סֵפֶר|n|tr=séfer}} * {{Z|io}}: {{W+|io|libro}} * {{Z|ig}}: {{W-|ig|akwụkwọ}} * {{Z|ang}}: {{W-|ang|bōc|m}} * {{Z|enm}}: {{W-|enm|bok}} * {{Z|en}}: {{W+|en|book}} * {{Z|izh}}: {{W-|izh|kirja}} * {{Z|inh}}: {{W-|inh|китаб}} * {{Z|ia}}: {{W+|ia|libro}} * {{Z|iu}}: {{W+|iu|ᕿᒥᕐᕈᐊᑦ}} *: {{Z|iu}}: {{W-|iu|unikkausik}} * {{Z|sga}}: {{W-|sga|lebor|n}} * {{Z|ga}}: {{W+|ga|leabhar|n}} * {{Z|ist}}: {{W-|ist|leîbro|n}} * {{Z|it}}: {{W+|it|libro|n}} * {{Z|is}}: {{W+|is|bók|m}} * {{Z|ja}}: {{W+|ja|本|tr=ほん, hon}}, {{W+|ja|書籍|tr=しょせき, shoseki}}, {{W+|ja|ブック|tr=bukku}} * {{Z|kaw}}: {{W-|kaw|tulis}} * {{Z|jv}}: {{W+|jv|buku}}, {{W+|jv|layang}}, {{W-|jv|serat}} * {{Z|kbd}}: {{W-|kbd|тхылъ}} * {{Z|kab}}: {{W-|kab|adlis}} * {{Z|kl}}: {{W-|kl|atuagaq}} * {{Z|xal}}: {{W-|xal|дегтр}} * {{Z|kn}}: {{W+|kn|ಪುಸ್ತಕ}} * {{Z|krc}}: {{W-|krc|китап}} * {{Z|kaa}}: {{W-|kaa|kitap}} * {{Z|krl}}: {{W-|krl|kirju}} * {{Z|csb}}: {{W-|csb|knéga|m}}, {{W-|csb|knyga|m}}, {{W-|csb|knëga|m}}, {{W-|csb|ksążka|m}} * {{Z|ca}}: {{W+|ca|llibre|n}} * {{Z|qu}}: {{W+|qu|liwru}}, {{W+|qu|p'anqa}} * {{Z|ky}}: {{W+|ky|китеп}} * {{Z|kg}}: {{W-|kg|dibuku}} * {{Z|ki}}: {{W-|ki|rifuku}} * {{Z|si}}: {{W+|si|පොත}} * {{Z|rw}}: {{W-|rw|igitabo|c7|c8}} * {{Z|gil}}: {{W-|gil|boki}} * {{Z|kis}}: {{W-|kis|egetabu}} * {{Z|kpv}}: {{W-|kpv|небӧг}}, {{W-|kpv|книга}} * {{Z|kok}}: {{W-|kok|पुस्तक}} * {{Z|ko}}: {{W-|ko|책(冊)}}, {{W-|ko|도서(圖書)}} * {{Z|kw}}: {{W-|kw|lyver|n}} * {{Z|co}}: {{W+|co|libru|n}} * {{Z|lou}}: {{W-|lou|liv}} * {{Z|mfe}}: {{W-|mfe|liv}} * {{Z|crs}}: {{W-|crs|liv}} * {{Z|kum}}: {{W-|kum|китап}} * {{Z|fkv}}: {{W-|fkv|kirja}} * {{Z|kj}}: {{W-|kj|embo}} * {{Z|lad}}: *: Îbranî: {{W-|lad|ליב׳רו|n}} *: Latînî: {{W-|lad|livro|n}} * {{Z|lbe}}: {{W-|lbe|лу}} * {{Z|lkt}}: {{W-|lkt|wówapi}} * {{Z|la}}: {{W+|la|liber|n}}, {{W-|la|caudex|n}} * {{Z|lv}}: {{W+|lv|grāmata|m}} * {{Z|lo}}: {{W+|lo|ປຶ້ມ}}, {{W+|lo|ປຶ້ມຂຽນ}}, {{W-|lo|ຫນັງສື}}, {{W-|lo|ສັດຖະ}}, {{W-|lo|ພັບ}} * {{Z|lzz}}: {{W-|lzz|სუპარა}} * {{Z|lez}}: {{W-|lez|улуб}}, {{W-|lez|ктаб}}, {{W-|lez|дафтар}} * {{Z|mhx}}: {{W-|mhx|mug sug' paug'}}, {{W-|mhx|tung" paug'}}, {{W-|mhx|paug'}} * {{Z|ln}}: {{W-|ln|búku|c9a|c10a}} * {{Z|lij}}: {{W-|lij|lìbbro|n}}, {{W-|lij|libbro}} * {{Z|li}}: {{W+|li|book|m}} * {{Z|lt}}: {{W+|lt|knyga|m}} * {{Z|liv}}: {{W-|liv|rōntõz}} * {{Z|lmo}}: {{W-|lmo|liber}} * {{Z|lg}}: {{W-|lg|ekitabo}} * {{Z|luy}}: {{W-|luy|sitabu}} * {{Z|lb}}: {{W+|lb|Buch|nt}} * {{Z|mk}}: {{W+|mk|книга|m}} * {{Z|mg}}: {{W+|mg|boky}} * {{Z|ml}}: {{W+|ml|പുസ്തകം}} * {{Z|pqm}}: {{W-|pqm|wikhikon}} * {{Z|ms}}: {{W+|ms|buku}}, {{W+|ms|kitab}}, {{W+|ms|pustaka}} * {{Z|mt}}: {{W+|mt|ktieb|n}} * {{Z|mnc}}: {{W-|mnc|ᠪᡳᡨᡥᡝ}}, {{W-|mnc|ᠴᠠᡤᠠᠨ}}, {{W-|mnc|ᠨᠣᠮᡠᠨ}} * {{Z|gv}}: {{W-|gv|lioar|n}} * {{Z|mns-nor}}: {{W-|mns-nor|кнӣга}} * {{Z|mi}}: {{W+|mi|pukapuka}} * {{Z|mr}}: {{W+|mr|पुस्तक|m}} * {{Z|mhr}}: {{W-|mhr|книга}} * {{Z|mrc}}: {{W-|mrc|onyor}} * {{Z|yua}}: {{W-|yua|juʼun}} * {{Z|hu}}: {{W+|hu|könyv}} * {{Z|xmf}}: {{W-|xmf|სუფარა|n}}, {{W-|xmf|წინგი}} * {{Z|egy}}: {{W-egy|mḏꜣt|m|h=Y1:t*Z1-V12:Z1}}, {{W-egy|šfdw|n|h=S:f-d-w-V12}} * {{Z|mvi}}: {{W-|mvi|書物|tr=すぃむくㇲ, simuks}} * {{Z|mwl}}: {{W-|mwl|lhibro|n}} * {{Z|mdf}}: {{W-|mdf|книга}} * {{Z|mn}}: *: Kirîlî: {{W+|mn|ном}}, {{W+|mn|бичиг}} *: Mongolî: {{W-|mn|ᠨᠣᠮ}}, {{W-|mn|ᠪᠢᠴᠢᠭ᠋}} * {{Z|mnw}}: {{W-|mnw|လိက် အုပ်|tr=lòik up}} * {{Z|wmw}}: {{W-|wmw|kitabu}}, {{W-|wmw|buku}}, {{W-|wmw|livro}} * {{Z|nah}}: {{W+|nah|amoxtli}} *: {{Z|nci}}: {{W-|nci|āmoxtli}} * {{Z|gld}}: {{W-|gld|дангса}} * {{Z|nap}}: {{W-|nap|lìbbro|n}} * {{Z|nv}}: {{W-|nv|naaltsoos}} * {{Z|nds}}: *: {{Z|nds-nl}}: {{W-|nds-nl|book|nt}} *: {{Z|nds-de}}: {{W-|nds-de|Book|nt}} * {{Z|yrk}}: {{W-|yrk|книга}}, {{W-|yrk|толаӈгобць’}} * {{Z|ne}}: {{W-|ne|पुस्तक}}, {{W+|ne|किताप}} * {{Z|new}}: {{W-|new|सफू}} * {{Z|niv}}: {{W-|niv|питғы}} * {{Z|nog}}: {{W-|nog|китап}} * {{Z|no}}: *: {{Z|no}}: {{W+|no|bok|n|m}} *: {{Z|nn}}: {{W+|nn|bok|m}} * {{Z|ood}}: {{W-|ood|ʼoʼohana}} * {{Z|ojw}}: {{W-|ojw|masinahikan}} * {{Z|oj}}: {{W-|oj|mazina'igan}} * {{Z|ryu}}: {{W-|ryu|書物|tr=すむち, sumuchi, しむち, shimuchi}} * {{Z|pro}}: {{W-|pro|libre}} * {{Z|oc}}: {{W+|oc|libre|n}} * {{Z|or}}: {{W+|or|ବହି}} * {{Z|oaa}}: {{W-|oaa|бичихэ}} * {{Z|os}}: {{W-|os|чиныг}} * {{Z|ota}}: {{W-|ota|كتاب|tr=kitâb}} * {{Z|ug}}: {{W+|ug|كىتاب}} * {{Z|uz}}: {{W+|uz|kitob}} * {{Z|pi}}: {{W-|pi|potthaka}} *: {{Z|pi}}: {{W-|pi|पोत्थक}} *: {{Z|pi}}: {{W-|pi|โปตถะกะ}} * {{Z|pap}}: {{W-|pap|buki}} * {{Z|paw}}: {{W-|paw|raáwihaakaraaʾit}}, {{W-|paw|raáwihaakaraaʾiitusuʾ}} * {{Z|ps}}: {{W+|ps|کتاب|n|tr=ketāb}} * {{Z|pms}}: {{W-|pms|lìber}} * {{Z|pdt}}: {{W-|pdt|Buak|nt}} * {{Z|pox}}: {{W-|pox|bükvoi|p}} * {{Z|pl}}: {{W+|pl|książka|m}}, {{W+|pl|księga|m}} * {{Z|pt}}: {{W+|pt|livro|n}} * {{Z|prg}}: {{W-|prg|lāiskas|n}} * {{Z|pkp}}: {{W-|pkp|lau}}, {{W-|pkp|puka}} * Puncabî: *: Şaxmuxî: {{W+|pa|پستک|n}}, {{W+|pa|کتاب|m|tr=ktāb}} *: Gurmuxî: {{W-|pa|ਪੁਸਤਕ|n}}, {{W-|pa|ਕਿਤਾਬ}} * {{Z|kk}}: {{W+|kk|кітап}} *: {{Z|kk}}: {{W-|kk|كىتاپ}} * {{Z|cop}}: {{W-|cop|ϫⲱⲙ|n}} * {{Z|rah}}: {{W-|rah|কাওছা|tr=káosa}} * {{Z|mwr}}: {{W-|mwr|पोथी|tr=pothī|m}} * {{Z|rgn}}: {{W-|rgn|lìvar|n}} * {{Z|rm}}: {{W-|rm|cudesch}} * {{Z|rom}}: {{W-|rom|ginadyi|m}} * {{Z|ro}}: {{W+|ro|carte|m}} * {{Z|ru}}: {{W+|ru|кни́га|m}}, {{W+|ru|кни́жка|m}} * {{Z|rue}}: {{W-|rue|кни́га|m}} * {{Z|se}}: {{W-|se|girji}} * {{Z|sma}}: {{W-|sma|gærja}} * {{Z|smn}}: {{W-|smn|kirje}} * {{Z|sjd}}: {{W-|sjd|кыррьй}}, {{W-|sjd|кнӣга}} * {{Z|smj}}: {{W-|smj|girjje}} * {{Z|sms}}: {{W-|sms|ǩeʹrjj}} * {{Z|sgs}}: {{W-|sgs|kninga|m}} * {{Z|sa}}: {{W+|sa|पुस्तक|nt}}, {{W+|sa|ग्रन्थ|nt}} * {{Z|scn}}: {{W+|scn|libbru|n}} * {{Z|sky}}: {{W-|sky|laumea}} * {{Z|szl}}: {{W-|szl|kniga|m}} * {{Z|sd}}: {{W+|sd|ڪتاب|n|tr=kitāb|cuda=ڪِتابُ}} * {{Z|srn}}: {{W-|srn|buku}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|књи̏га|m}} *: Latînî: {{W+|sh|knjȉga|m}} * {{Z|syc}}: {{W-|syc|ܟܬܒܐ|n|tr=kṯāḇā}} * {{Z|syl}}: {{W-|syl|ꠛꠂ}} * {{Z|sco}}: {{W-|sco|beuk}} * {{Z|cu}}: *: Kirîlî: {{W-|cu|боукꙑ|m}}, {{W-|cu|кънигꙑ|m-p}} * {{Z|orv}}: {{W-|orv|кънига|m}} * {{Z|sk}}: {{W+|sk|kniha|m}} * {{Z|sl}}: {{W+|sl|knjíga|m}} * {{Z|zlw-slv}}: {{W-|zlw-slv|knega|m}} * {{Z|so}}: {{W+|so|buug|n}}, {{W-|so|kitaab|n}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|knigły|m-p}} *: {{Z|hsb}}: {{W-|hsb|kniha|m}} * {{Z|st}}: {{W+|st|buka}} * {{Z|es}}: {{W+|es|libro|n}} * {{Z|su}}: {{W-|su|ᮘᮥᮊᮥ}} * {{Z|xsv}}: {{W-|xsv|laiskas|n}} * {{Z|sva}}: {{W-|sva|ლა̈ირ}} * {{Z|sw}}: {{W+|sw|kitabu}}, {{W+|sw|vitabu|p}} * {{Z|ss}}: {{W-|ss|íncwadzí|c9|c10}} * {{Z|sv}}: {{W+|sv|bok|g}} * {{Z|shn}}: {{W-|shn|ပပ်ႉ}}, {{W-|shn|ၸႃႇဢုၵ်ႉ}} * {{Z|sn}}: {{W-|sn|bhuku}} * {{Z|cjs}}: {{W-|cjs|ном|tr=nom}}, {{W-|cjs|книга}} * {{Z|tab}}: {{W-|tab|китаб}} * {{Z|tg}}: {{W+|tg|китоб}} * {{Z|tl}}: {{W+|tl|libro}}, {{W+|tl|aklat}} * {{Z|ta}}: {{W+|ta|நூல்}}, {{W+|ta|புத்தகம்}} * {{Z|roa-tar}}: {{W-|roa-tar|libbre|n}} * {{Z|shi}}: {{W-|shi|ⴰⵔⵔⴰ|n}} * {{Z|th}}: {{W+|th|หนังสือ}}, {{W+|th|สมุด}} * {{Z|te}}: {{W+|te|పుస్తకం}}, {{W-|te|పొత్తం}} * {{Z|crh}}: {{W-|crh|kitap}} * {{Z|tt}}: {{W+|tt|китап}} * {{Z|tet}}: {{W-|tet|livru}} * {{Z|tig}}: {{W-|tig|ክታብ}} * {{Z|ti}}: {{W-|ti|መጽሓፍ}}, {{W-|ti|መጽሐፍ}} * {{Z|otk}}: {{W-|otk|𐰋𐰃𐱅𐰏}} * {{Z|tr}}: {{W+|tr|kitap}}, {{W+|tr|betik}} * {{Z|tk}}: {{W-|tk|kitap}} * {{Z|bo}}: {{W-|bo|དེབ}}, {{W-|bo|ཕྱག་དེབ}} * {{Z|tli}}: {{W-|tli|x’úx’}} * {{Z|tpi}}: {{W-|tpi|buk}} * {{Z|txb}}: {{W-|txb|postak}} * {{Z|tn}}: {{W+|tn|buka}} * {{Z|tum}}: {{W-|tum|buku}} * {{Z|tvl}}: {{W-|tvl|tusi}} * {{Z|tyv}}: {{W-|tyv|ном}} * {{Z|udi}}: {{W-|udi|ҝирк}} * {{Z|udm}}: {{W-|udm|книга}} * {{Z|unm}}: {{W-|unm|lekhikàn}} * {{Z|ur}}: {{W+|ur|کِتاب|m|tr=kitāb}}, {{W-|ur|پُسْتَک|m|tr=pustak}}, {{W-|ur|بُک|m|tr=buk}} * {{Z|urh}}: {{W-|urh|e̖be}} * {{Z|uk}}: {{W-|uk|кни́жка|m}}, {{W+|uk|кни́га|m}} * {{Z|vec}}: {{W-|vec|łìbro|n}} * {{Z|vep}}: {{W-|vep|kirj}} * {{Z|vi}}: {{W+|vi|sách}}, {{W+|vi|sổ}}, {{W+|vi|sách giáo khoa}} * {{Z|vo}}: {{W+|vo|buk}} * {{Z|vot}}: {{W-|vot|tširjõ}} * {{Z|wa}}: {{W+|wa|live|n}} * {{Z|war}}: {{W-|war|basahon}}, {{W-|war|barasahon}} * {{Z|cy}}: {{W+|cy|llyfr|n}} * {{Z|wrh}}: {{W-|wrh|garrandarang}} * {{Z|wym}}: {{W-|wym|bihła|nt}}, {{W-|wym|büch}} * {{Z|wo}}: {{W-|wo|[[tééré]] bi}}, {{W+|wo|téere}} * {{Z|wuh}}: {{W-|wuh|huaiqa}} * {{Z|kjh}}: {{W-|kjh|кинде}} * {{Z|km}}: {{W+|km|សៀវភៅ}} * {{Z|xh}}: {{W-|xh|incwadi|c9|c10}} * {{Z|yai}}: {{W-|yai|китоб}} * {{Z|sah}}: {{W-|sah|кинигэ}} * {{Z|tao}}: {{W-|tao|vakong}} * {{Z|yi}}: {{W-|yi|בוך|nt}}, {{W-|yi|ספֿר|n|tr=seyfer}}, {{W-|yi|חיבור|n|tr=khiber}} * {{Z|yo}}: {{W-|yo|ìwé}} * {{Z|el}}: {{W+|el|βιβλίο|nt}}, {{W+|el|τόμος|n}} *: Kevn: {{W-|grc|βιβλίον|nt}} * {{Z|za}}: {{W-|za|saw}} * {{Z|zu}}: {{W+|zu|ibhuku|c5|c6}}, {{W+|zu|incwadi|c9|c10}} {{werger-bin}} :{{werger çavkanî|en|book|oldid=75472768|beş=Ev qismê Wergerê}} cmfjzo9q13edlzhrmk1uw8pdrlunt0q horî 0 4695 6347229 6327298 2026-08-30T18:21:14Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347229 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/ʕhoːˈɾiː/}} * {{ku-kîte}} === Navdêr === [[Wêne:Houris on Camelback - 15th century Persia.png|thumb|250px|Horiyên siwar, nîgarek ji Îranê ji sedsala 16em]] {{navdêr|ku|z=m}} # {{f|ku|Îslam|Zerdeştî}} [[zerî|Zeriyên]] [[ciwan]] û [[spehî]] yên ku tê bawerkirin ku li [[biheşt]]ê di xizmeta [[zelam]]an de ne #* {{jêder|ku|jêgirtin=Li axretê 70 '''horî''', li vê dinyayê 40 horî, oxxxxxx!|Lotikxane.com, 7/2008}} # Her [[keç]]a yan [[jin]]a [[pirr]] [[spehî]] û [[delal]]. #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|حۆری}} ==== Formên alternatîv ==== {{kol3|ku |hûrî<crz:1> }} ==== Jê ==== {{kol3|ku |horîtî }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|حورية}} (ḧûriye<sup>t</sup>) ji {{ji|ira}}, hevreha {{hv|pal||hurust|sc=Latn}} (jinên spehî), {{hv|ae||hu-rewse-|sc=Latn}} ji ''hu-'' ([[spehî]], [[baş]], [[xweş]] - binere [[hewa]]) + ''-rewse-'' ([[dirûv]], [[şikil]], [[awa]] - binere [[xwerist]], [[sirişt]]). Hê berî îslamê di berhemên zerdeştî de, bi taybetî di ''Erde Viraz Namek'' (Kitêba Virazê Rast) de, tê behskirin. Paşî li ber ''Erde Viraz Namek''ê herwiha [[mi'rac|Mi'raca]] Mihemed-pêxember jî hatiye nivîsîn. Herwiha hevreha [[huner]], [[hinêr]]. ==== Bide ber ==== {{kol3|ku |esmer |kezîzer |zerî }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Kleinigkeit}} {{mê}}, {{W|de|Jungfrau}} {{mê}}, {{W|de|Scherbe|guman=erê}} * {{Z|fa}}: {{W|fa|جزئی بودن}}, {{W|fa|حوری}}, {{W|fa|ریزبودن}}, {{W|fa|جزءیات}} * {{Z|en}}: {{W|en|distraction}}, {{W|en|precisianism}}, {{W|en|exactitude|guman=erê}}, {{W|en|minutia|guman=erê}} * {{Z|tr}}: {{W|tr|huri}} {{werger-bin}} 58njy7bf3tqxnjbpbz19azmrb2k9hpn deqe 0 4795 6347333 6304892 2026-08-31T10:24:54Z Wikihez 7344 guhartina pêşketî (DefSideBoxes) 6347333 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/dɛˈqɛː/}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # 60 [[sanî]]; 1/60 ji [[saet]]ekê. #* {{bêmînak|ku}} # [[dem|Dem]]eke kurt lê [[nediyar]]. #: ''Ka '''deqe'''kê bise, ez ê vegerim...'' ==== Tewandin ==== {{ku-tewîn-nav/nû|mê|guherto=hemû}} ==== Formên alternatîv ==== * [[deqîqe]] ==== Hevmane ==== * [[xulek]] ==== Jê ==== * [[deqeyî]] ==== Etîmolojî ==== Kurtkirina {{q|ku|deqîqe}} ji {{deyn|ar|ku|دَقِيقَة}} ji {{g|ar|دَقِيق‎|w=hûr, biçûk}} ku herwiha serekaniya peyva {{q|ku|deqîq}} ya kurdî ye jî. ==== Bide ber ==== * [[çirke]] * [[saet]] * [[çarêk]] * [[demjimêrk]] ==== Werger ==== {{werger-ser|16 sanî, 1/60 ji saetekê}} * {{Z|ab}}: {{W-|ab|аминуҭ}} * {{Z|ady}}: {{W-|ady|такъикъ}} * {{Z|af}}: {{W+|af|minuut}} * {{Z|sq}}: {{W-|sq|imtash|nt}}, {{W+|sq|minutë|n}} * {{Z|de}}: {{W+|de|Minute|n}} *: {{Z|gmw-cfr}}: {{W-|gmw-cfr|Menutt}} * {{Z|am}}: {{W-|am|ደቂቃ}} * {{Z|an}}: {{W-|an|minuto|nt}} * {{Z|aii}}: {{W-|aii|ܕܲܩܝܼܩܵܐ|nt|tr=dāqīqa}} * {{Z|rup}}: {{W-|rup|minutã|n}} * {{Z|ast}}: {{W+|ast|minutu|nt}} * {{Z|az}}: {{W+|az|dəqiqə}} * {{Z|eu}}: {{W+|eu|minutu}} * {{Z|ba}}: {{W-|ba|минут}} * {{Z|be}}: {{W-|be|хвілі́на|n}} * {{Z|bal}}: {{W-|bal|منٹ|tr=minaṭṭ}} * {{Z|bn}}: {{W+|bn|মিনিট}} * {{Z|br}}: {{W+|br|munut|nt}} * {{Z|bg}}: {{W-|bg|мину́та|n}} * {{Z|my}}: {{W+|my|မိနစ်}} * {{Z|cs}}: {{W+|cs|minuta|n}} * {{Z|chr}}: {{W-|chr|ᎢᏯᏔᏬᏍᏔᏅᎢ}} * {{Z|ny}}: {{W-|ny|miniti}}, {{W-|ny|mphindi}} * {{Z|zh}}: *: {{Z|yue}}: {{W-|yue|分鐘|tr=fan1 zung1}} *: {{Z|dng}}: {{W-|dng|фынҗун}}, {{W-|dng|минута}} *: {{Z|hak}}: {{W-|hak|分鐘|tr=fûn-chûng}} *: {{Z|cmn}}: {{W+|cmn|分鐘|tr=fēnzhōng}}, {{W+|cmn|分|tr=fēn}} *: {{Z|cdo}}: {{W-|cdo|分鐘|tr=hŭng-cṳ̆ng}} *: {{Z|nan}}: {{W+|nan|分鐘|tr=hun-cheng}} *: {{Z|wuu}}: {{W-|wuu|分鐘}} * {{Z|da}}: {{W+|da|minut|nt}} * {{Z|dtp}}: {{W-|dtp|minit}} * {{Z|id}}: {{W+|id|menit}}, {{W-|id|minit}}, {{W+|id|minuta}} * {{Z|ar}}: {{W+|ar|دَقِيقَة|n}} *: {{Z|afb}}: {{W-|afb|دِقيقة|tr=digīgə}} *: {{Z|ary}}: {{W-|ary|دقيقة|n|tr=dagīga|cuda=دَقِيقة}} *: {{Z|ary}}: {{W-|ary|دقيقة|n|tr=dqīqa}} * {{Z|hy}}: {{W+|hy|րոպե}}, {{W-|hy|վայրկեան}} *: {{Z|xcl}}: {{W-|xcl|վայրկեան}} * {{Z|eo}}: {{W+|eo|minuto}} * {{Z|et}}: {{W+|et|minut}}, {{W+|et|mint}} * {{Z|gur}}: {{W-|gur|miniti}} * {{Z|fa}}: {{W+|fa|دقیقه|tr=daqiqe}} * {{Z|fo}}: {{W-|fo|minuttur|nt}} * {{Z|fj}}: {{W+|fj|miniti}} * {{Z|fi}}: {{W+|fi|minuutti}} * {{Z|fr}}: {{W+|fr|minute|n}} * {{Z|fy}}: {{W-|fy|minút|g}} * {{Z|gd}}: {{W-|gd|mionaid|n}} * {{Z|gl}}: {{W-|gl|minuto|nt}} * {{Z|gu}}: {{W-|gu|મિનિટ}} * {{Z|ka}}: {{W-|ka|წუთი}} * {{Z|ha}}: {{W-|ha|minti}} * {{Z|hi}}: {{W+|hi|मिनट|nt}} * {{Z|mww}}: {{W-|mww|feeb}} * {{Z|nl}}: {{W+|nl|minuut|g}} * {{Z|he}}: {{W-|he|דַּקָּה|n|tr=daká}} * {{Z|io}}: {{W+|io|minuto}} * {{Z|enm}}: {{W-|enm|mynute}} * {{Z|en}}: {{W+|en|minute}} * {{Z|inh}}: {{W-|inh|минот}} * {{Z|ia}}: {{W-|ia|minuta}} * {{Z|ga}}: {{W+|ga|nóiméad|nt}}, {{W-|ga|bomaite|nt}} * {{Z|it}}: {{W+|it|minuto|nt}} * {{Z|is}}: {{W+|is|mínúta|n}} * {{Z|ja}}: {{W+|ja|分|tr=ふん, fun}} * {{Z|kbd}}: {{W-|kbd|дакъикъэ}} * {{Z|xal}}: {{W-|xal|агчм}} * {{Z|kn}}: {{W+|kn|ನಿಮಿಷ}} * {{Z|ca}}: {{W+|ca|minut|nt}} * {{Z|qu}}: {{W-|qu|chinini}} * {{Z|ky}}: {{W+|ky|мүнөт}} * {{Z|si}}: {{W+|si|විනාඩිය}}, {{W-|si|මිනිත්‍තුව}} * {{Z|ko}}: {{W+|ko|분}} * {{Z|la}}: {{W+|la|minuta|n}}, {{W-|la|horae pars sexagesima}} * {{Z|lv}}: {{W-|lv|minūte|n}} * {{Z|lo}}: {{W+|lo|ນາທີ}} * {{Z|lez}}: {{W-|lez|декьикьа}} * {{Z|lt}}: {{W+|lt|minutė|n}} * {{Z|lb}}: {{W-|lb|Minutt|n}} * {{Z|mk}}: {{W+|mk|минута|n}} * {{Z|ml}}: {{W+|ml|മിനിറ്റ്}} * {{Z|ms}}: {{W+|ms|minit}} * {{Z|mt}}: {{W-|mt|minuta|n}} * {{Z|mi}}: {{W-|mi|miniti}} * {{Z|mr}}: {{W-|mr|मिनिट}} * {{Z|hu}}: {{W+|hu|perc}} * {{Z|gdq}}: {{W-|gdq|دقيقت}} * {{Z|mn}}: *: {{Z|mn}}: {{W+|mn|минут}}, {{W+|mn|жижиг}} *: {{Z|mn}}: {{W-|mn|ᠮᠢᠨᠦ᠋ᠲ}}, {{W-|mn|ᠵᠢᠵᠢᠭ}} * {{Z|nv}}: {{W-|nv|dah alzhin}} * {{Z|ne}}: {{W-|ne|मिनेट}} * {{Z|nrf}}: {{W-|nrf|minnute|n}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|minutt|nt}} *: {{Z|nn}}: {{W+|nn|minutt|nt|nt}} * {{Z|oj}}: {{W-|oj|diba'igaans}} * {{Z|oc}}: {{W+|oc|minuta}} * {{Z|or}}: {{W-|or|ମିନଟ}} * {{Z|ug}}: {{W-|ug|مىنۇت}} * {{Z|uz}}: {{W+|uz|daqiqa}} * {{Z|ps}}: {{W+|ps|دقيقه|n|tr=daqiqá}}, {{W-|ps|منټ|n|tr=minëṭ}} * {{Z|pdt}}: {{W-|pdt|Minnut|n}} * {{Z|pl}}: {{W+|pl|minuta|n}} * {{Z|pt}}: {{W+|pt|minuto|nt}} * {{Z|pa}}: {{W-|pa|ਮਿੰਟ}} * {{Z|kk}}: {{W+|kk|минут}} * {{Z|cop}}: {{W-|cop|ⲥⲟⲩⲥⲟⲩ}} * {{Z|rgn}}: {{W-|rgn|minùt|nt}} * {{Z|rm}}: {{W-|rm|minuta|n}}, {{W-|rm|minut|nt}} * {{Z|ro}}: {{W+|ro|minut|nt}} * {{Z|ru}}: {{W-|ru|мину́та|n}} * {{Z|sc}}: *: {{Z|sc}}: {{W-|sc|minutu|nt}} * {{Z|ceb}}: {{W-|ceb|gutlo}}, {{W-|ceb|mitna}}, {{W-|ceb|minuto}} * {{Z|scn}}: {{W+|scn|minutu|nt}} * {{Z|sh}}: *: {{Z|sh}}: {{W-|sh|мину́та|n}}, {{W-|sh|мѝнӯт|nt}} *: {{Z|sh}}: {{W+|sh|minúta|n}}, {{W+|sh|mìnūt|nt}} * {{Z|sco}}: {{W-|sco|meenit}} * {{Z|sk}}: {{W+|sk|minúta|n}} * {{Z|sl}}: {{W+|sl|minuta|n}} * {{Z|so}}: {{W-|so|daqiiqad}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|minuta|n}} * {{Z|es}}: {{W+|es|minuto|nt}} * {{Z|sw}}: {{W+|sw|dakika}} * {{Z|sv}}: {{W+|sv|minut|g}} * {{Z|tg}}: {{W-|tg|дақиқа}} * {{Z|tl}}: {{W+|tl|minuto}}, {{W+|tl|sandali}} * {{Z|ta}}: {{W+|ta|நிமிடம்}}, {{W+|ta|நிமிஷம்}}, {{W+|ta|மணித்துளி}}, {{W+|ta|நுணுத்தம்}} * {{Z|th}}: {{W+|th|นาที}} * {{Z|te}}: {{W+|te|నిమిషము}} * {{Z|crh}}: {{W-|crh|daqqa}} * {{Z|tt}}: {{W-|tt|минут}} * {{Z|ti}}: {{W-|ti|ደቒቕ}} * {{Z|tr}}: {{W+|tr|dakika}} * {{Z|tk}}: {{W-|tk|minut}} * {{Z|bo}}: {{W-|bo|སྐར་མ}} * {{Z|tyv}}: {{W-|tyv|минут}}, {{W-|tyv|минута}} * {{Z|ur}}: {{W-|ur|دقیقہ|nt|tr=daqīqā}}, {{W-|ur|مِنَٹ|nt|tr=minaṭ}} * {{Z|uk}}: {{W-|uk|хвили́на|n}} * {{Z|vi}}: {{W+|vi|phút}} * {{Z|vo}}: {{W+|vo|minut}} * {{Z|wa}}: {{W+|wa|munute|n}} * {{Z|cy}}: {{W+|cy|munud}} * {{Z|km}}: {{W+|km|នាទី}} * {{Z|sah}}: {{W-|sah|мүнүүтэ}} * {{Z|yi}}: {{W+|yi|מינוט|n}} * {{Z|el}}: {{W+|el|λεπτό|nt}} * {{Z|za}}: {{W-|za|faencung}} {{werger-bin}} :{{werger çavkanî|en|minute|beş=Ev qismê Wergerê|oldid=75764140}} {{werger-ser|demeke kurt lê nediyarkirî}} * {{Z|de}}: {{W+|de|Moment|n}} * {{Z|ast}}: {{W+|ast|minutu|n}} * {{Z|eu}}: {{W+|eu|minutu}}, {{W+|eu|momentu}} * {{Z|bn}}: {{W+|bn|মিনিট}}, {{W-|bn|মুহূর্ত}} * {{Z|bg}}: {{W-|bg|моме́нт|n}} * {{Z|cs}}: {{W+|cs|minuta|m}}, {{W+|cs|minutka|m}}, {{W+|cs|vteřina|m}}, {{W+|cs|chvilka|m}} * {{Z|ny}}: {{W-|ny|mphindi}} * {{Z|hy}}: {{W+|hy|րոպե}} * {{Z|et}}: {{W-|et|hetk}}, {{W-|et|hetk}}, {{W+|et|moment}} * {{Z|fi}}: {{W+|fi|hetki}}, {{W+|fi|hetkinen}} * {{Z|fr}}: {{W+|fr|minute|m}}, {{W+|fr|moment|n}}, {{W+|fr|instant|n}} * {{Z|gd}}: {{W-|gd|mionaid|m}} * {{Z|gl}}: {{W-|gl|minuto|n}} * {{Z|nl}}: {{W+|nl|minuutje|nt}}, {{W+|nl|secondje|nt}}, {{W+|nl|moment|nt}} * {{Z|he}}: {{W-|he|רֶגַע|tr=réga|n}}, {{W-|he|זְמַן קָצָר|n|tr=zman katsár}} * {{Z|enm}}: {{W-|enm|mynute}} * {{Z|en}}: {{W+|en|minute}}, {{W+|en|moment}} * {{Z|it}}: {{W+|it|attimo|n}}, {{W+|it|momento|n}} * {{Z|is}}: {{W-|is|augablik|nt}}, {{W+|is|mínúta|m}} * {{Z|ca}}: {{W+|ca|segon|n}}, {{W+|ca|moment|n}} * {{Z|lt}}: {{W+|lt|minutė|m}}, {{W-|lt|akimirka|m}} * {{Z|mk}}: {{W-|mk|моме́нт|n}}, {{W+|mk|минута|m}} * {{Z|ms}}: {{W-|ms|sekejap}} * {{Z|mt}}: {{W-|mt|minuta}} * {{Z|hu}}: {{W+|hu|perc}}, {{W+|hu|pillanat}} * {{Z|nrf}}: {{W-|nrf|minnute|m}} * {{Z|no}}: *: {{Z|nb}}: {{W+|nb|øyeblikk|nt}} * {{Z|pl}}: {{W+|pl|minuta|m}}, {{W+|pl|minutka|m}}, {{W+|pl|chwila|m}}, {{W+|pl|moment|m-in}} * {{Z|pt}}: {{W+|pt|instante|n}}, {{W+|pt|minuto|n}}, {{W+|pt|momento|n}} * {{Z|ro}}: {{W+|ro|minut|nt}} * {{Z|ru}}: {{W-|ru|мину́та|m}} * {{Z|ceb}}: {{W-|ceb|kadiyot}} * {{Z|sco}}: {{W-|sco|meenit}} * {{Z|es}}: {{W+|es|minuto|n}}, {{W+|es|momento|n}} * {{Z|sw}}: {{W+|sw|dakika}} * {{Z|sv}}: {{W+|sv|ögonblick|nt}} * {{Z|tl}}: {{W+|tl|sandali}} * {{Z|th}}: {{W-|th|แป๊บเดียว|tr=bpáep dieow}} * {{Z|tr}}: {{W+|tr|dakika}} * {{Z|vi}}: {{W+|vi|lát}}, {{W+|vi|chốc}} * {{Z|wa}}: {{W+|wa|munute|m}}, {{W+|wa|houbonde|m}}, {{W+|wa|åvé|m}} * {{Z|el}}: {{W+|el|στιγμή|m}}, {{W+|el|λεπτό|nt}} {{werger-bin}} :{{werger çavkanî|en|minute|beş=Ev qismê Wergerê|oldid=75764140}} q2v934c4l2a7z38qt6smugh1wlfqynp amade 0 6721 6347257 6334829 2026-08-30T20:21:49Z ~2026-45593-87 15272 /* Rengdêr */ 6347257 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{deng|ku|LL-Q36163 (kmr)-Ebulfîda-amade.wav|dever=Bidlîs}} * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|amade}} {{rengdêr|ku}} # [[hazir]], [[çêkirî]], [[sazkirî]], [[dirist]], gîf, têz, gellalle, berhav: #: ''Xwarin '''amade''' ye.'' # [[beşdar]], [[cemawer]], li [[der]]ekê anku [[cih]]ekê #: ''Ez li [[civîn]]a [[duhî]] ne '''amade''' bûm.'' (Ez ne li civîna duhî bûm.) ==== Ji wêjeya klasîk ==== * {{J:Mem û Zîn:1692|jêgirtin=Adabê sefa û zindeganî<br />'''Amade''' ke şerbet û te'aman<br />Azade ke cariye û xulaman}} ==== Bi alfabeyên din ==== * {{ku-ar|ئاماده}} ==== Hevmane ==== * [[hazir]] * [[berhev]] (2) * [[nazir]] ==== Jê ==== {{kol2|ku|cure=Jê |amadeber |amadeberî |amadebûyî |amadehî |amadekar |amadekarî |amadeker |amadekerî |amadekirî |amadetî |amadeyî |amade bûn<q:lêker> |amade kirin<q:lêker> |amadebûn<q:navdêr> |amadekirin<q:navdêr> |amadekirî<q:rengdêr> }} ==== Etîmolojî ==== Bi riya {{deyn|ckb|ku|ئاماده|tr=amade}}, herdu ji {{ji|fa|ku|آماده|tr=amade}} ji {{g|fa|آمادن|tr=amaden|w=[[berdest kirin]]}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|bereit}}, {{W+|de|fertig}}, {{W+|de|gar}}, {{W+|de|parat}} * {{Z|as}}: {{W-|as|সাজু}} * {{Z|av}}: {{W-|av|хӏадураб}} * {{Z|az}}: {{W+|az|hazır}} * {{Z|eu}}: {{W-|eu|prest}}, {{W-|eu|gertu}} * {{Z|ba}}: {{W-|ba|әҙер|sc=Cyrl}} * {{Z|be}}: {{W-|be|гато́вы|sc=Cyrl}} * {{Z|bn}}: {{W+|bn|প্রস্তুত}} * {{Z|bg}}: {{W+|bg|готов}} * {{Z|ce}}: {{W-|ce|кийча}} * {{Z|cs}}: {{W+|cs|připravený|n}}, {{W+|cs|hotový}} * {{Z|zh}}: *: {{Z|cmn}}: {{W-|cmn|[[準備]][[好]][[的]]|tr=zhǔnbèi hǎo de}} * {{Z|ar}}: {{W-|ar|جَاهِز}}, {{W-|ar|مُسْتَعِدّ}} *: {{Z|arz}}: {{W-|arz|جاهز|tr=gāhiz}} * {{Z|hy}}: {{W+|hy|պատրաստ}} * {{Z|eo}}: {{W+|eo|preta}} * {{Z|fa}}: {{W+|fa|آماده|tr=âmâde}}, {{W+|fa|تیار|tr=tayyâr}}, {{W+|fa|رو به راه|tr=ru be râh}} * {{Z|fi}}: {{W+|fi|valmis}} * {{Z|fr}}: {{W+|fr|prêt|n}}, {{W+|fr|prête|m}} * {{Z|gd}}: {{W-|gd|deiseil}}, {{W-|gd|ullamh}} * {{Z|got}}: {{W-|got|𐌼𐌰𐌽𐍅𐌿𐍃}} * {{Z|gu}}: {{W-|gu|તૈયાર}}, {{W-|gu|સજ્જ}} * {{Z|ka}}: {{W-|ka|მზად}} * {{Z|haw}}: {{W-|haw|mākaukau}} * {{Z|hi}}: {{W+|hi|तैयार}}, {{W+|hi|मुस्तैद}}, {{W+|hi|सिद्ध}}, {{W+|hi|आमादा}}, {{W+|hi|तत्पर}}, {{W+|hi|सज्ज}}, {{W+|hi|तैनात}} * {{Z|nl}}: {{W+|nl|gereed}}, {{W+|nl|klaar}} * {{Z|he}}: {{W-|he|מוּכָן|tr=mukhan}} * {{Z|io}}: {{W+|io|pronta}} * {{Z|ang}}: {{W-|ang|gearu}} * {{Z|en}}: {{W+|en|ready}} * {{Z|izh}}: {{W-|izh|valmis}} * {{Z|inh}}: {{W-|inh|кийча}} * {{Z|ga}}: {{W-|ga|réidh}}, {{W-|ga|ullamh}} * {{Z|it}}: {{W+|it|pronto}}, {{W+|it|preparato}} * {{Z|is}}: {{W+|is|tilbúinn|n}} * {{Z|ja}}: {{W-|ja|[[用意]][[の]][[出来る|出来た]]|tr=よういのできた, yōi no dekita}}, {{W-|ja|出来上がり|tr=できあがり, dekiagari}}, {{W-|ja|[[準備]][[の]][[出来る|出来た]]||tr=じゅんびのできた, junbi no dekita}} * {{Z|kbd}}: {{W-|kbd|хьэзыр}} * {{Z|ca}}: {{W+|ca|llest}} * {{Z|ko}}: {{W+|ko|[[준비]][[되다|된]]}} * {{Z|ltg}}: {{W-|ltg|gotovs|n}}, {{W-|ltg|sasarūss|n}} * {{Z|la}}: {{W+|la|aptus}}, {{W+|la|parātus}}, {{W-|la|promptus}} * {{Z|lv}}: {{W-|lv|gatavs}} * {{Z|lo}}: {{W-|lo|ພ້ອມ}} * {{Z|mk}}: {{W-|mk|спремен}}, {{W-|mk|готов}} * {{Z|ms}}: {{W-|ms|sedia}} * {{Z|mi}}: {{W-|mi|reri}}, {{W-|mi|takatū}} * {{Z|mr}}: {{W-|mr|तयार}} * {{Z|hu}}: {{W+|hu|kész}}, {{W+|hu|készen}} * {{Z|mn}}: {{W+|mn|бэлэн}} * {{Z|ne}}: {{W+|ne|तयार}} * {{Z|no}}: {{W+|no|klar}}, {{W+|no|parat}} * {{Z|oc}}: {{W-|oc|lèst}} * {{Z|os}}: {{W-|os|цӕттӕ}} * {{Z|pdt}}: {{W-|pdt|reed}} * {{Z|pl}}: {{W+|pl|gotowy}} * {{Z|pt}}: {{W+|pt|pronto|n}}, {{W+|pt|preparado|n}} * {{Z|pa}}: {{W+|pa|ਤਿਆਰ}} * {{Z|kk}}: {{W-|kk|даяр}} * {{Z|ru}}: {{W+|ru|гото́вый}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|спреман}}, {{W-|sh|готов}} *: Latînî: {{W+|sh|spreman}}, {{W+|sh|gotov}} * {{Z|sco}}: {{W-|sco|boun}} * {{Z|sk}}: {{W-|sk|hotový}} * {{Z|sl}}: {{W-|sl|pripravljen}}, {{W-|sl|gotov}}, {{W+|sl|nared}} * {{Z|so}}: {{W-|so|diyaar}} * Sorbî: *: {{Z|dsb}}: {{W-|dsb|gótowy}} * {{Z|es}}: {{W+|es|preparado}}, {{W+|es|listo}} * {{Z|sv}}: {{W+|sv|beredd}}, {{W+|sv|redo}} * {{Z|zdj}}: {{W-|zdj|tiyari}} * {{Z|tg}}: {{W-|tg|тайор}} * {{Z|th}}: {{W+|th|พร้อม}} * {{Z|te}}: {{W-|te|సిద్ధం}}, {{W+|te|తయారు}} * {{Z|tr}}: {{W+|tr|hazır}}, {{W+|tr|anık}} * {{Z|txb}}: {{W-|txb|ārwer}} * {{Z|ur}}: {{W-|ur|تیار|tr=taiyār}} * {{Z|uk}}: {{W+|uk|гото́вий|sc=Cyrl}} * {{Z|vi}}: {{W+|vi|sẵn sàng}} * {{Z|cy}}: {{W+|cy|parod}} * {{Z|km}}: {{W-|km|ត្រៀមខ្លួនជាស្រេច}} * {{Z|yai}}: {{W-|yai|тайор|tr=tayor}} * {{Z|sah}}: {{W-|sah|бэлэм}} * {{Z|yi}}: {{W-|yi|פֿאַרטיק}} * {{Z|el}}: {{W+|el|έτοιμος}} *: Kevn: {{W-|grc|ἑτοῖμος}} {{werger-bin}} :{{werger çavkanî|en|ready|beş=Ev qismê Wergerê|oldid=75757105}} == {{ziman|tr}} == === Rengdêr === {{rengdêr|tr}} # amade, [[hazir]] #* {{bêmînak|tr}} syaj4z7jmcev4n3tr0put6xhe0g4s1s hazir 0 6726 6347258 6335511 2026-08-30T20:22:49Z ~2026-45593-87 15272 /* Rengdêr */ 6347258 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|hazir}} {{rengdêr|ku}} # [[amade]], [[eleste]], [[eywez]], [[nazir]], [[çêkirî]], [[sazkirî]], [[dirist]], [[berhev]], gîf, têz, gellalle, #: {{mk|ku|Xwarin '''hazir''' e.}} # [[berdest]] #: {{mk|ku|Halê '''hazir'''.|niha, vê gavê|birêz=1}} # [[beşdar]], [[cemawer]], li [[der]]ekê anku [[cih]]ekê #: {{mk|ku|Ez li [[civîn]]a [[duhî]] ne '''hazir''' bûm.|Ez ne li civîna duhî bûm.|birêz=1}} ==== Ji wêjeya klasîk ==== * {{J:Mela Hisênê Bateyî:Mewlûda Kurdî|jêgirtin=Her kesê '''hazir''' biket ew yek te'am<br />Ba buxur û şerbet û qedrek temam}} ==== Jê ==== {{stûn| * {{mj|lêker}} [[hazir bûn]] * {{mj|lêker}} [[hazir kirin]] * {{mj|lêker}} [[hazir hebûn]] * {{mj|navdêr}} [[hazirbûn]] * {{mj|navdêr}} [[hazirkirin]] * {{mj|navdêr}} [[hazirhebûn]] * {{mj|rengdêr}} [[hazirkirî]] * {{mj|biwêj}} [[hazir û nazir]] * [[berhazir]] * [[berhazirî]] * [[hazirbûyî]] * [[hazirî]] * [[hazirkar]] * [[hazirkarî]] * [[hazirker]] * [[hazirkerî]] * [[hazirkirî]] * [[hazirtî]] }} ==== Etîmolojî ==== Ji {{ji|ar|ku|حَاضِر‎}}. ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W+|af|bereid}}, {{W+|af|gereed}}, {{W+|af|klaar}} * {{Z|de}}: {{W+|de|bereit}}, {{W+|de|fertig}}, {{W|de|anwesend}}, {{W|de|parat}}, {{W|de|vorhanden}}, {{W|de|vorbereitet}}, {{W|de|vorrätig|guman=erê}}, {{W|de|bereitwilligst|guman=erê}}, {{W|de|willens|guman=erê}}, {{W|de|zugegen|guman=erê}}, {{W|de|Anwesender|guman=erê}} * {{Z|cs}}: {{W+|cs|připravený}} * {{Z|da}}: {{W+|da|færdig}} * {{Z|id}}: {{W+|id|siap}} * {{Z|ar}}: {{W+|ar|حاضر}}, {{W+|ar|جاهز}}, {{W|ar|مضارع|guman=erê}} * {{Z|eo}}: {{W+|eo|preta}} * {{Z|fa}}: {{W+|fa|آمده}}, {{W+|fa|حاضر}}, {{W+|fa|حضور}}, {{W+|fa|آماده}}, {{W+|fa|فراهم|guman=erê}} * {{Z|fo}}: {{W+|fo|liðugur}}, {{W+|fo|til reiðar}} * {{Z|fi}}: {{W+|fi|valmis}} * {{Z|fr}}: {{W+|fr|prêt}}, {{W+|fr|prête}} * {{Z|fy}}: {{W+|fy|dien}}, {{W+|fy|ree}} * {{Z|gd}}: {{W+|gd|ullamh}}, {{W+|gd|deiseil}} * {{Z|nl}}: {{W+|nl|af}}, {{W+|nl|afgelopen}}, {{W+|nl|gereed}}, {{W+|nl|klaar}} * {{Z|io}}: {{W+|io|pronta}} * {{Z|ang}}: {{W+|ang|gearu}} * {{Z|en}}: {{W+|en|ready}}, {{W+|en|prepared}}, {{W+|en|finished}}, {{W+|en|readymade}}, {{W+|en|ripe}}, {{W+|en|make}}, {{W+|en|poised|guman=erê}}, {{W|en|up one's sleeve|guman=erê}}, {{W|en|present|guman=erê}} * {{Z|it}}: {{W+|it|pronto}} * {{Z|is}}: {{W+|is|tillbúinn}} * {{Z|ca}}: {{W+|ca|disposat}}, {{W+|ca|preparat}}, {{W+|ca|prest}} * {{Z|ms}}: {{W+|ms|siap}} * {{Z|pap}}: {{W+|pap|kla}} * {{Z|pl}}: {{W+|pl|gotowy}} * {{Z|pt}}: {{W+|pt|pisposto}}, {{W+|pt|prestes}}, {{W+|pt|pronto}} * {{Z|ro}}: {{W+|ro|gata}} * {{Z|es}}: {{W+|es|listo}}, {{W+|es|dispuesto}}, {{W+|es|preparado}} * {{Z|sw}}: {{W+|sw|tayari}} * {{Z|sv}}: {{W+|sv|färdig}}, {{W+|sv|redo}}, {{W+|sv|tillreds}} * {{Z|tr}}: {{W+|tr|hazır}}, {{W+|tr|amade}}, {{W+|tr|anık}}, {{W+|tr|lüp}}, {{W+|tr|müsait}}, {{W|tr|müheyye|guman=erê}} {{werger-bin}} nxjd2lq0pvryamp5n4bhj5swk26rvpw lala 0 11205 6347240 6346256 2026-08-30T18:41:24Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347240 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku}} # [[fêrker]], [[hînker]], [[perwerdeker]], [[mamoste]], [[dersder]], [[waneder]], [[ilimder]], [[mielim]] #* {{jêder-websîte|ku|jêgirtin=[Malbata Ehmedê Xanî] mamosteyên ('''lalayên''') mîrzadeyên mîran bûne û di medreseyên bilind ên merkezên mîrayetiyê de midderisî kirine.|nivîskar=Mûrad Ciwan|sernav=Hin belgeyên nuh li ser Ahmedê Xanî|websîte=Netkurd.com|sal=7/2005}} ==== Jê ==== {{kol3|ku |lalahî |lalatî |lalayane |lalayî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== {{kol3|ku |lale }} ==== Werger ==== {{werger-ser}} * {{Z|ar}}:{{W|ar|مدرس|guman=erê}}, {{W|ar|معلم|guman=erê}} {{werger-bin}} ldyuivqhhv8rp0gij7r9ltjuuh9h3m8 xunav 0 15106 6347328 6341013 2026-08-31T10:04:38Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347328 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/xʊˈnɑːv/}} * {{kîte|ku|xu|nav}} === Navdêr === [[Wêne:Dew on grass Luc Viatour.jpg|thumb|xunav]] {{navdêr|ku|z=m}} # [[çip]]ên [[baran]]ê (bi taybetî ya [[çip]]-çip [[barîn|dibare]]), [[dilop]], [[lib]]ên [[av]]a [[baran]]ê #* {{J:Melayê Cizîrî:Dîwana Melayê Cizîrî|jêgirtin=دست قدرت کو هلاڤیت ژ بژنا ته نقاب</br>بجمالا جبروتي مه نمان پرده و حجاب</br>لگلین ته‌ی تر و نازک کو سحر گرتی '''خناڤ'''|tr=Destê qudret ko hilavêt ji bejna te niqab</br>Bi cemala ceberûtî me neman perde û hicab</br>Li gulên tey ter û nazik ko seher girtî '''xunav'''}} #* {{J:Mehmed Uzun:Mirina Kalekî Rind:1987|jêgirtin=weke dilopên '''xunava''' nîsanê}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|خونـاڤ}} * (''Klasîk'') {{g|ku|sc=Arab|خناڤ|tr=xwinav}} ==== Formên alternatîv ==== * [[xunavî]] * [[xwinav]] * [[xwinavî]] ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== * [[hinav]] * [[ximav]] ==== Herwiha binêre ==== * [[nixte]] ==== Bi zaravayên din ==== * {{Z|ckb}}: {{W-|ckb|شەونم}}, {{W-|ckb|خوناو}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W-|de|feiner Regen}}, {{W+|de|Tau|guman=erê}} {{n}} * {{Z|ar}}: {{W-|ar|البغشة|guman=erê}}, {{W-|ar|السدي|guman=erê}}, {{W-|ar|الغفق|guman=erê}}, {{W-|ar|اللث|guman=erê}}, {{W-|ar|الندى|guman=erê}} * {{Z|fa}}: {{W+|fa|ژاله}}, {{W+|fa|شبنم}} * {{Z|en}}: {{W+|en|dew}}, {{W+|en|frost|guman=erê}}, {{W+|en|mist|guman=erê}}, {{W+|en|moisture|guman=erê}}, {{W+|en|clammy|guman=erê}}, {{W+|en|clamminess|guman=erê}} * {{Z|tr}}: {{W+|tr|ahmak ıslatan}}, {{W-|tr|çilentî}}, {{W+|tr|çise}}, {{W+|tr|çisenti}}, {{W+|tr|çiy}} {{werger-bin}} 5etdk6cf3v6iejzjmbq3e4r4rjdhrmh gala 0 15578 6347241 6307031 2026-08-30T18:41:42Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347241 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{navdêr|ku|z=m}} # [[fest]], [[festîval]], [[şahî]], [[cejn]], [[şehyan]], [[pîrozî]] #* {{jêder|ku|''Darîn bû kurdê salê'', Nefel.com, 1/2006|jêgirtin=Komîkerê kurd ... bi henekên xwe yên li ser nakokiyên kulturî yên kurdan û swêdiyan atmosfera '''galayê''' heta dawiyê zindî hişt.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |gale }} ==== Jê ==== {{kol3|ku |galayane |galayî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== {{kol3|ku |galerî }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Gala|f|guman=erê}} * {{Z|tr}}: {{W+|tr|gala}} {{werger-bin}} == {{ziman|en}} == === Bilêvkirin === * {{deng|en|en-uk-gala.ogg|dever=QY}} === Navdêr === {{navdêr|en}} # [[#Kurdî|gala]], [[fest]], [[festîval]], [[şahî]], [[cejn]], [[şehyan]], [[pîrozî]] #* {{bênimûne|en}} == {{ziman|qu}} == === Navdêr === {{navdêr|qu}} # {{f|qu|anatomî}} [[çerm#ku|çerm]] #* {{bênimûne|qu}} == {{ziman|tk}} == === Navdêr === {{navdêr|tk}} # {{f|tk|avahî}} {{g|ku|keleh}} #* {{bênimûne|tk}} === Çavkanî === {{rûpela wergerê|tk|keleh}} 27zdwkdg0s36shs289oktlttxumofix nîr 0 20567 6347296 6336075 2026-08-30T23:42:29Z Wikihez 7344 /* Etîmolojî */ 6347296 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} === Navdêr === [[Wêne:Bullock_yokes.jpg|thumb|Du gayên bi '''nîrekî''' bi hev ve hatine [[girê dan|girêdan]].]] {{navdêr|ku|z=n}} # [[dar|Darê]] ku du [[ga]] û [[gamêş]] pê tên [[zeft]]kirin dema [[cot]] pê tê kirin yan [[erebe]] pê tê [[kêşan]]. #: {{hevmane|ku|yûx|cûx|tûxt|bondurẍa}} #* {{bêmînak|ku}} # {{f|ku|mecazî}} [[zilm]], [[zordestî]], [[stem]], [[bindestî]], [[koletî]] #* {{bêmînak|ku}} ==== Ji wêjeya klasîk ==== * {{J:Mem û Zîn:1692|jêgirtin=Yekrû ne li nik te kufr û îman</br>Yeksû ne li nik te xuld û '''nîran'''</br>Qehra xwe bikî eger tu zahir}} ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|نیر}} ==== Têkildar ==== * {{g|ku|basole}} ==== Etîmolojî ==== Ji {{deyn|ar|ku|نير|tr=nîr}}. Hevreha soranî {{g|ckb|نیر|tr=nîr}}, [[kurdiya başûrî]] ''nîr'', ''[[nîre]]'', zazakî ''[[nîre]]'', îbrî [[ניר]] (nîr), aramî [[ܢܝܪܐ]] (nîra), {{hv|akk||nîru}}<ref>[http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=6896&language=id]</ref>. ==== Bide ber ==== {{kol3|ku |bîr |çîr |dîr |gîr |hîr |jîr |kîr |lîr |mîr |pîr |sîr |şîr |tîr |zîr }} ==== Herwiha binêre ==== {{kol3|ku |nar |nêr |nor |nûr |tûxt |ox |dox }} ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|zgjedhë}} {{mê}} * {{Z|goh}}: {{W-|goh|joch|n}} * {{Z|de}}: {{W+|de|Joch}} {{nt}} * {{Z|cs}}: {{W+|cs|jařmo}} {{nt}} * {{Z|da}}: {{W+|da|åg}} * {{Z|ar}}: {{W-|ar|نير}} {{n}} * {{Z|eo}}: {{W+|eo|jugo}} * {{Z|et}}: {{W+|et|ike}} * {{Z|fa}}: {{W+|ku|یوغ}} (yûẍ) * {{Z|fi}}: {{W+|fi|ies}} * {{Z|fr}}: {{W+|fr|joug|n}} * {{Z|gl}}: {{W+|gl|xugo}} {{n}} * {{Z|grk-ita}}: {{W-|grk-ita|zio}} {{n}} * {{Z|io}}: {{W+|io|yugo}} * {{Z|ang}}: {{W-|ang|geoc|cuda=ġeoc}} {{nt}} * {{Z|en}}: {{W+|en|yoke}} (1,2) ; {{W+|en|servitude}}, {{W+|en|slavery}} * {{Z|ca}}: {{W+|ca|jou}} * {{Z|co}}: {{W-|co|coppiu}} * {{Z|la}}: {{W-|la|iugum}} {{nt}} * {{Z|lt}}: {{W-|lt|jungas}} {{n}} * {{Z|hu}}: {{W+|hu|iga}}, {{W+|hu|járom}} * {{Z|pl}}: {{W+|pl|jarzmo}} * {{Z|ro}}: {{W+|ro|jug|n}} * {{Z|ru}}: {{W+|ru|иго}} {{nt}} * {{Z|sh}}: {{W+|sh|igo}} {{nt}}, {{W+|sh|jaram}} {{n}} * {{Z|sk}}: {{W-|sk|jarmo}} {{nt}} * {{Z|es}}: {{W+|es|yugo}} {{n}} * {{Z|sv}}: {{W+|sv|ok}} {{nt}} * {{Z|tr}}: {{W+|tr|boyunduruk}} * {{Z|wa}}: {{W+|wa|djeu}} {{n}} * {{Z|el}}: {{W+|el|ζυγός}} {{n}} {{werger-bin}} === Çavkanî === {{Çavkanî}} pjfx5qi0lh3bcrxrp4g6kz4e7e6wkdo barist 0 20951 6347225 6298150 2026-08-30T18:14:21Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347225 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[bilindahî]], [[hecim]] #* {{jêder-websîte|ku|jêgirtin=Bi alîkariya bîrkariyê (mathematics) xisletên çalên reş hatine jimartin û encamên balkêş jê derketine. Nîvtîra (radius) gewdê ko '''barista''' (mass) stêrekê li nav bihêwire, da rakêşa wê bigehe wê hêzê, ko êdî ti foton ji nav nikaribin derkevin 3 kîlometre. Û navê nîvtîra Schwarzschild lê tê kirin.|nivîskar=Zagrosê Hajo|sernav=Em çawa dikarin bizanin ku çalên reş hene?|websîte=Netkurd.com|sal=6/2006}} # [[giranî]], [[qursî]], [[wezin]] ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Jê ==== {{kol3|ku|cure=Jê |bêbarist |bêbaristî |bibarist |bibaristî |baristdar |baristdarî |baristdêr |baristdêrî }} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W-|fa|هضم غذا}} * {{Z|fi}}: {{W+|fi|massa}} * {{Z|en}}: {{W+|en|mass}}, {{W+|en|bulk}}, {{W+|en|conglomeration}} * {{Z|tr}}: {{W+|tr|hacim}}, {{W+|tr|kütle|guman=erê}} {{werger-bin}} ho6khp6buuq103feicljkxir1zkposl rawêj 0 21585 6347233 6346255 2026-08-30T18:32:41Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347233 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # Kesa/ê ku li ser [[nav]]ê kesekî yan [[dezgeh]]ekê [[peyivîn|diaxive]] yan [[agadarî|agadariyan]] dide. #: {{hevmane|ku|berdevk|peyvdar}} #* {{jêder|ku|jêgirtin=Nameya Talebanî ji bal '''rabêjê''' wî Celal Maşte ve hat gihandin Sergey Lavrovê wezîrê derve yê Rusyayê bi amadebûna balyozê Iraqê li Moskovayê.|Netkurd.com, 7/2006}} #* {{jêder|ku|jêgirtin=Di wê semînarê de, ku Aştî Hewramî mêvanê taybet bû, bi gotarek general James Johns dest pê kir. Navborî '''rawêjkarê''' berê yê asayişa niştimanî ya Emerîkayê bû|http://rudaw.net/kurmanci/business/18042013}} # [[qisekirin]], [[xeberdan]] #* {{jêder|ku|jêgirtin=Birêz Martin Kopler nîgeraniya Neteweyên Yekgirtî li asta rûdawên dawiya li Iraqê derbirî û ragihand ku Neteweyên Yekgirtî li nêzîk ve çavdêriya rewşa Iraqê dike û rolekî zêdetir û bi bandortir jî li hevkarîkirina aliyê siyasiyên Iraqê ya bi navê gihîştina çareseriyekî rasteqîne û bingehîn de digre û tekez jî li wê yekê kir ku ev hevdîtin ji bo '''rawêj''' û agahdarbûne li raman û nêrînên Serok Barzanî ya di derbarê qeyrana hukimraniya li Iraqê û çawayiya derketina ji wê qeyranê, ji ber ku hemû pêşbîniyên berê yên birêz bi wî awayî derketin ku îro tê dîtin.|http://www.rojevakurd.com/politik/12173-Serok-Herma-Kurdistan-pwaziya-nner-taybetiy-Neteweyn-Yekgirt-kir.html}} # [[şêwirmendî]] ==== Formên alternatîv ==== {{kol3|ku |ravêj |rabêj<q:bi şaşî carna wek> }} ==== Jê ==== {{kol3|ku |rawêj kirin<crz:lêker> |rawêjkirin<crz:navdêr> |rawêjî |rawêjîtî |rawêjtî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|-wêj}}, ji {{pêş|ku|ra-|gotin}}, bide ber {{hv|la|predictō|w=ra-gotin}} (>{{hv|en|predict}}). ==== Bide ber ==== {{kol3|ku |rabêj }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Weise|m}}, {{W+|de|Redner|n}} * {{Z|zh}}: {{W-|zh|新闻发言人}} * {{Z|ar}}: {{W-|ar|الراوي}}, {{W-|ar|الحكيم}}, {{W-|ar|الناصح}}, {{W-|ar|مقدم المشورة}} * {{Z|fa}}: {{W+|fa|قیافه}}, {{W+|fa|تخمین|guman=erê}}, {{W+|fa|شک کردن|guman=erê}}, {{W+|fa|مشورت|guman=erê}} * {{Z|fi}}: [[edustaja]] (jonkun puolesta puhuva), {{W+|fi|konsultointi}} * {{Z|fr}}: {{W+|fr|porte-parole}} * {{Z|nl}}: {{W+|nl|woordvoerder}} * {{Z|en}}: {{W+|en|spokesperson}}, {{W+|en|spokesman}}, {{W+|en|spokeswoman}}, {{W+|en|default}}, {{W+|en|consul}}, {{W+|en|confeder|guman=erê}}, {{W-|en|conferer|guman=erê}}, {{W+|en|consulting}} * {{Z|sv}}: {{W-|sv|förespråkare}}, {{W-|sv|språkrör}} * {{Z|tr}}: {{W+|tr|sözcü}}, {{W+|tr|danışma}}, {{W+|tr|istişare}}, {{W+|tr|meyil}}, {{W+|tr|muaşeret}}, {{W+|tr|tahmin}}, {{W+|tr|varsayım}}, {{W+|tr|zan}}, {{W+|tr|farz}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # [[axiftin]], [[qisekirin]] #* {{bêmînak|ckb}} otsozekydyvfngso5v5zmjdcc7tv8um 6347234 6347233 2026-08-30T18:35:37Z Wikihez 7344 +nimûneya bikaranînê bi amûra « [[Mediawiki:Gadget-wikt.add-examples|Nimûne zêde bike]] » (v2.0). 6347234 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # Kesa/ê ku li ser [[nav]]ê kesekî yan [[dezgeh]]ekê [[peyivîn|diaxive]] yan [[agadarî|agadariyan]] dide. #: {{hevmane|ku|berdevk|peyvdar}} #* {{jêder|ku|jêgirtin=Nameya Talebanî ji bal '''rabêjê''' wî Celal Maşte ve hat gihandin Sergey Lavrovê wezîrê derve yê Rusyayê bi amadebûna balyozê Iraqê li Moskovayê.|Netkurd.com, 7/2006}} #* {{jêder|ku|jêgirtin=Di wê semînarê de, ku Aştî Hewramî mêvanê taybet bû, bi gotarek general James Johns dest pê kir. Navborî '''rawêjkarê''' berê yê asayişa niştimanî ya Emerîkayê bû|http://rudaw.net/kurmanci/business/18042013}} #* {{jêder-websîte|ku|nivîskar=Mutlu Çevîroglu|websîte=Rudaw|sernav=Aştî Hewramî: Pêwîst e Emerîka di pirsa petrola Iraqê de bê alî be|url=https://rudaw.net/kurmanci/categories/business/962347|tarîx=2013-04-18|jêgirtin=Di wê semînarê de, ku Aştî Hewramî mêvanê taybet bû, bi gotarek general James Johns dest pê kir. Navborî '''rawêjkarê''' berê yê asayişa niştimanî ya Emerîkayê bû.}} # [[qisekirin]], [[xeberdan]] #* {{jêder|ku|jêgirtin=Birêz Martin Kopler nîgeraniya Neteweyên Yekgirtî li asta rûdawên dawiya li Iraqê derbirî û ragihand ku Neteweyên Yekgirtî li nêzîk ve çavdêriya rewşa Iraqê dike û rolekî zêdetir û bi bandortir jî li hevkarîkirina aliyê siyasiyên Iraqê ya bi navê gihîştina çareseriyekî rasteqîne û bingehîn de digre û tekez jî li wê yekê kir ku ev hevdîtin ji bo '''rawêj''' û agahdarbûne li raman û nêrînên Serok Barzanî ya di derbarê qeyrana hukimraniya li Iraqê û çawayiya derketina ji wê qeyranê, ji ber ku hemû pêşbîniyên berê yên birêz bi wî awayî derketin ku îro tê dîtin.|http://www.rojevakurd.com/politik/12173-Serok-Herma-Kurdistan-pwaziya-nner-taybetiy-Neteweyn-Yekgirt-kir.html}} # [[şêwirmendî]] ==== Formên alternatîv ==== {{kol3|ku |ravêj |rabêj<q:bi şaşî carna wek> }} ==== Jê ==== {{kol3|ku |rawêj kirin<crz:lêker> |rawêjkirin<crz:navdêr> |rawêjî |rawêjîtî |rawêjtî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|-wêj}}, ji {{pêş|ku|ra-|gotin}}, bide ber {{hv|la|predictō|w=ra-gotin}} (>{{hv|en|predict}}). ==== Bide ber ==== {{kol3|ku |rabêj }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Weise|m}}, {{W+|de|Redner|n}} * {{Z|zh}}: {{W-|zh|新闻发言人}} * {{Z|ar}}: {{W-|ar|الراوي}}, {{W-|ar|الحكيم}}, {{W-|ar|الناصح}}, {{W-|ar|مقدم المشورة}} * {{Z|fa}}: {{W+|fa|قیافه}}, {{W+|fa|تخمین|guman=erê}}, {{W+|fa|شک کردن|guman=erê}}, {{W+|fa|مشورت|guman=erê}} * {{Z|fi}}: [[edustaja]] (jonkun puolesta puhuva), {{W+|fi|konsultointi}} * {{Z|fr}}: {{W+|fr|porte-parole}} * {{Z|nl}}: {{W+|nl|woordvoerder}} * {{Z|en}}: {{W+|en|spokesperson}}, {{W+|en|spokesman}}, {{W+|en|spokeswoman}}, {{W+|en|default}}, {{W+|en|consul}}, {{W+|en|confeder|guman=erê}}, {{W-|en|conferer|guman=erê}}, {{W+|en|consulting}} * {{Z|sv}}: {{W-|sv|förespråkare}}, {{W-|sv|språkrör}} * {{Z|tr}}: {{W+|tr|sözcü}}, {{W+|tr|danışma}}, {{W+|tr|istişare}}, {{W+|tr|meyil}}, {{W+|tr|muaşeret}}, {{W+|tr|tahmin}}, {{W+|tr|varsayım}}, {{W+|tr|zan}}, {{W+|tr|farz}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # [[axiftin]], [[qisekirin]] #* {{bêmînak|ckb}} e4pd6yz88bejwrrxp96r1zxah7tei5t 6347235 6347234 2026-08-30T18:35:47Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347235 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # Kesa/ê ku li ser [[nav]]ê kesekî yan [[dezgeh]]ekê [[peyivîn|diaxive]] yan [[agadarî|agadariyan]] dide. #: {{hevmane|ku|berdevk|peyvdar}} #* {{jêder|ku|jêgirtin=Nameya Talebanî ji bal '''rabêjê''' wî Celal Maşte ve hat gihandin Sergey Lavrovê wezîrê derve yê Rusyayê bi amadebûna balyozê Iraqê li Moskovayê.|Netkurd.com, 7/2006}} #* {{jêder-websîte|ku|nivîskar=Mutlu Çevîroglu|websîte=Rudaw|sernav=Aştî Hewramî: Pêwîst e Emerîka di pirsa petrola Iraqê de bê alî be|url=https://rudaw.net/kurmanci/categories/business/962347|tarîx=2013-04-18|jêgirtin=Di wê semînarê de, ku Aştî Hewramî mêvanê taybet bû, bi gotarek general James Johns dest pê kir. Navborî '''rawêjkarê''' berê yê asayişa niştimanî ya Emerîkayê bû.}} # [[qisekirin]], [[xeberdan]] #* {{jêder|ku|jêgirtin=Birêz Martin Kopler nîgeraniya Neteweyên Yekgirtî li asta rûdawên dawiya li Iraqê derbirî û ragihand ku Neteweyên Yekgirtî li nêzîk ve çavdêriya rewşa Iraqê dike û rolekî zêdetir û bi bandortir jî li hevkarîkirina aliyê siyasiyên Iraqê ya bi navê gihîştina çareseriyekî rasteqîne û bingehîn de digre û tekez jî li wê yekê kir ku ev hevdîtin ji bo '''rawêj''' û agahdarbûne li raman û nêrînên Serok Barzanî ya di derbarê qeyrana hukimraniya li Iraqê û çawayiya derketina ji wê qeyranê, ji ber ku hemû pêşbîniyên berê yên birêz bi wî awayî derketin ku îro tê dîtin.|http://www.rojevakurd.com/politik/12173-Serok-Herma-Kurdistan-pwaziya-nner-taybetiy-Neteweyn-Yekgirt-kir.html}} # [[şêwirmendî]] ==== Formên alternatîv ==== {{kol3|ku |ravêj |rabêj<q:bi şaşî carna wek> }} ==== Jê ==== {{kol3|ku |rawêj kirin<crz:lêker> |rawêjkirin<crz:navdêr> |rawêjî |rawêjîtî |rawêjtî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|-wêj}}, ji {{pêş|ku|ra-|gotin}}, bide ber {{hv|la|predictō|w=ra-gotin}} (>{{hv|en|predict}}). ==== Bide ber ==== {{kol3|ku |rabêj }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Weise|m}}, {{W+|de|Redner|n}} * {{Z|zh}}: {{W-|zh|新闻发言人}} * {{Z|ar}}: {{W-|ar|الراوي}}, {{W-|ar|الحكيم}}, {{W-|ar|الناصح}}, {{W-|ar|مقدم المشورة}} * {{Z|fa}}: {{W+|fa|قیافه}}, {{W+|fa|تخمین|guman=erê}}, {{W+|fa|شک کردن|guman=erê}}, {{W+|fa|مشورت|guman=erê}} * {{Z|fi}}: [[edustaja]] (jonkun puolesta puhuva), {{W+|fi|konsultointi}} * {{Z|fr}}: {{W+|fr|porte-parole}} * {{Z|nl}}: {{W+|nl|woordvoerder}} * {{Z|en}}: {{W+|en|spokesperson}}, {{W+|en|spokesman}}, {{W+|en|spokeswoman}}, {{W+|en|default}}, {{W+|en|consul}}, {{W+|en|confeder|guman=erê}}, {{W-|en|conferer|guman=erê}}, {{W+|en|consulting}} * {{Z|sv}}: {{W-|sv|förespråkare}}, {{W-|sv|språkrör}} * {{Z|tr}}: {{W+|tr|sözcü}}, {{W+|tr|danışma}}, {{W+|tr|istişare}}, {{W+|tr|meyil}}, {{W+|tr|muaşeret}}, {{W+|tr|tahmin}}, {{W+|tr|varsayım}}, {{W+|tr|zan}}, {{W+|tr|farz}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # [[axiftin]], [[qisekirin]] #* {{bêmînak|ckb}} kln816gnmgac4txhp9d9vocdotmnhkm 6347236 6347235 2026-08-30T18:39:13Z Wikihez 7344 /* Navdêr */ 6347236 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # Kesa/ê ku li ser [[nav]]ê kesekî yan [[dezgeh]]ekê [[peyivîn|diaxive]] yan [[agadarî|agadariyan]] dide. #: {{hevmane|ku|berdevk|peyvdar}} #* {{jêder|ku|jêgirtin=Nameya Talebanî ji bal '''rabêjê''' wî Celal Maşte ve hat gihandin Sergey Lavrovê wezîrê derve yê Rusyayê bi amadebûna balyozê Iraqê li Moskovayê.|Netkurd.com, 7/2006}} #* {{jêder-websîte|ku|nivîskar=Mutlu Çevîroglu|websîte=Rudaw|sernav=Aştî Hewramî: Pêwîst e Emerîka di pirsa petrola Iraqê de bê alî be|url=https://rudaw.net/kurmanci/categories/business/962347|tarîx=2013-04-18|jêgirtin=Di wê semînarê de, ku Aştî Hewramî mêvanê taybet bû, bi gotarek general James Johns dest pê kir. Navborî '''rawêjkarê''' berê yê asayişa niştimanî ya Emerîkayê bû.}} # [[qisekirin]], [[xeberdan]] #* {{jêder-websîte|ku|jêgirtin=Birêz Martin Kopler nîgeraniya Neteweyên Yekgirtî li asta rûdawên dawiya li Iraqê derbirî û ragihand ku Neteweyên Yekgirtî li nêzîk ve çavdêriya rewşa Iraqê dike û rolekî zêdetir û bi bandortir jî li hevkarîkirina aliyê siyasiyên Iraqê ya bi navê gihîştina çareseriyekî rasteqîne û bingehîn de digre û tekez jî li wê yekê kir ku ev hevdîtin ji bo '''rawêj''' û agahdarbûne li raman û nêrînên Serok Barzanî ya di derbarê qeyrana hukimraniya li Iraqê û çawayiya derketina ji wê qeyranê, ji ber ku hemû pêşbîniyên berê yên birêz bi wî awayî derketin ku îro tê dîtin.|urlya-arşîvê=https://web.archive.org/web/20130115184426/http://www.rojevakurd.com/politik/12173-Serok-Herma-Kurdistan-pwaziya-nner-taybetiy-Neteweyn-Yekgirt-kir.html|url=http://www.rojevakurd.com/politik/12173-Serok-Herma-Kurdistan-pwaziya-nner-taybetiy-Neteweyn-Yekgirt-kir.html|tarîx=13.01.2013|sernav=Serokê Herêma Kurdistanê pêşwaziya nûnerê taybetiyê Neteweyên Yekgirtî kir|websîte=rojevakurd.com}} # [[şêwirmendî]] ==== Formên alternatîv ==== {{kol3|ku |ravêj |rabêj<q:bi şaşî carna wek> }} ==== Jê ==== {{kol3|ku |rawêj kirin<crz:lêker> |rawêjkirin<crz:navdêr> |rawêjî |rawêjîtî |rawêjtî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|-wêj}}, ji {{pêş|ku|ra-|gotin}}, bide ber {{hv|la|predictō|w=ra-gotin}} (>{{hv|en|predict}}). ==== Bide ber ==== {{kol3|ku |rabêj }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Weise|m}}, {{W+|de|Redner|n}} * {{Z|zh}}: {{W-|zh|新闻发言人}} * {{Z|ar}}: {{W-|ar|الراوي}}, {{W-|ar|الحكيم}}, {{W-|ar|الناصح}}, {{W-|ar|مقدم المشورة}} * {{Z|fa}}: {{W+|fa|قیافه}}, {{W+|fa|تخمین|guman=erê}}, {{W+|fa|شک کردن|guman=erê}}, {{W+|fa|مشورت|guman=erê}} * {{Z|fi}}: [[edustaja]] (jonkun puolesta puhuva), {{W+|fi|konsultointi}} * {{Z|fr}}: {{W+|fr|porte-parole}} * {{Z|nl}}: {{W+|nl|woordvoerder}} * {{Z|en}}: {{W+|en|spokesperson}}, {{W+|en|spokesman}}, {{W+|en|spokeswoman}}, {{W+|en|default}}, {{W+|en|consul}}, {{W+|en|confeder|guman=erê}}, {{W-|en|conferer|guman=erê}}, {{W+|en|consulting}} * {{Z|sv}}: {{W-|sv|förespråkare}}, {{W-|sv|språkrör}} * {{Z|tr}}: {{W+|tr|sözcü}}, {{W+|tr|danışma}}, {{W+|tr|istişare}}, {{W+|tr|meyil}}, {{W+|tr|muaşeret}}, {{W+|tr|tahmin}}, {{W+|tr|varsayım}}, {{W+|tr|zan}}, {{W+|tr|farz}} {{werger-bin}} == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb|sc=Latn}} # [[axiftin]], [[qisekirin]] #* {{bêmînak|ckb}} a7kahj9pto7zszfcfzgz93n4hl8lg9h rapirsî 0 25018 6347246 6325260 2026-08-30T18:50:22Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347246 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pirsîn|Pirsîn]]a ji [[xelk]]ê bo [[diyar]]kirina [[ray]]a wan li ser [[mijar]]ekê. #: {{hevmane|ku|anket|pirsname}} #* {{jêder|ku|''Şanoya Sindîbad Berî Wexerê'', Avestakurd.net, 8/2004|jêgirtin=Sebaret bi nirxandina şanoyê wek karek hunerî bi giştî û peyama wê bi taybetî, '''rapirsiyek''' ji bo bîr û rayên handeran li Duhokê encam da û tê de rêjeya 84% bi erênî nirxand.}} # [[referandûm]], [[gelpirsî]], [[dengdan]]a hemû [[milet]] li ser [[mijar]]ekê daku ew mijar bêt [[pejirandin]] yan [[red]]kirin #: {{nm|ku|Qanûna Bingehîn ya Yekîtiya Ewropayê li Frensayê û Holendayê di rapirsiyê de hat redkirin.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |rapirsiyarî |rapirsyarî |raypirsî |raypirsiyarî |raypirsyarî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|pirs|-î}} yan ji {{paş|ku|rapirs|-î}}. ==== Werger ==== {{werger-ser|anket}} * {{Z|de}}: {{W+|de|Enquete|f}}, {{W-|de|Rundfrage}}, {{W+|de|Umfrage|f}}, {{W+|de|Untersuchung|f}}, {{W+|de|Erhebung|f}}, {{W+|de|Ermittlung}}, {{W+|de|Meinungsforschung|f|guman=erê}} * {{Z|eo}}: {{W-|eo|enketo}} * {{Z|fo}}: {{W-|fo|spurnakanning}} * {{Z|fi}}: {{W+|fi|kysely}} * {{Z|nl}}: {{W+|nl|enquête}} * {{Z|en}}: {{W+|en|poll}}, {{W+|en|survey}}, {{W+|en|referendum|guman=erê}} * {{Z|ca}}: {{W+|ca|enquesta}}, {{W+|ca|investigació}} * {{Z|pt}}: {{W+|pt|inquérito}}, {{W+|pt|investigação}}, {{W+|pt|sindicância}} * {{Z|ru}}: {{W+|ru|анкета}} * {{Z|es}}: {{W+|es|encuesta}}, {{W+|es|investigación}} * {{Z|sv}}: {{W+|sv|enkät}}, {{W-|sv|rundfråga}}, {{W+|sv|opinionsundersökning}} * {{Z|tr}}: {{W+|tr|anket}}, {{W+|tr|sormaca}}, {{W+|tr|soruşturma}} {{werger-bin}} 03i6kn3wnsuvb9jpi242sj8sr2ksx0l 6347247 6347246 2026-08-30T18:52:00Z Wikihez 7344 /* Etîmolojî */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347247 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pirsîn|Pirsîn]]a ji [[xelk]]ê bo [[diyar]]kirina [[ray]]a wan li ser [[mijar]]ekê. #: {{hevmane|ku|anket|pirsname}} #* {{jêder|ku|''Şanoya Sindîbad Berî Wexerê'', Avestakurd.net, 8/2004|jêgirtin=Sebaret bi nirxandina şanoyê wek karek hunerî bi giştî û peyama wê bi taybetî, '''rapirsiyek''' ji bo bîr û rayên handeran li Duhokê encam da û tê de rêjeya 84% bi erênî nirxand.}} # [[referandûm]], [[gelpirsî]], [[dengdan]]a hemû [[milet]] li ser [[mijar]]ekê daku ew mijar bêt [[pejirandin]] yan [[red]]kirin #: {{nm|ku|Qanûna Bingehîn ya Yekîtiya Ewropayê li Frensayê û Holendayê di rapirsiyê de hat redkirin.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |rapirsiyarî |rapirsyarî |raypirsî |raypirsiyarî |raypirsyarî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ray<cuda:ra><t:ray>|pirs|-î}}. ==== Werger ==== {{werger-ser|anket}} * {{Z|de}}: {{W+|de|Enquete|f}}, {{W-|de|Rundfrage}}, {{W+|de|Umfrage|f}}, {{W+|de|Untersuchung|f}}, {{W+|de|Erhebung|f}}, {{W+|de|Ermittlung}}, {{W+|de|Meinungsforschung|f|guman=erê}} * {{Z|eo}}: {{W-|eo|enketo}} * {{Z|fo}}: {{W-|fo|spurnakanning}} * {{Z|fi}}: {{W+|fi|kysely}} * {{Z|nl}}: {{W+|nl|enquête}} * {{Z|en}}: {{W+|en|poll}}, {{W+|en|survey}}, {{W+|en|referendum|guman=erê}} * {{Z|ca}}: {{W+|ca|enquesta}}, {{W+|ca|investigació}} * {{Z|pt}}: {{W+|pt|inquérito}}, {{W+|pt|investigação}}, {{W+|pt|sindicância}} * {{Z|ru}}: {{W+|ru|анкета}} * {{Z|es}}: {{W+|es|encuesta}}, {{W+|es|investigación}} * {{Z|sv}}: {{W+|sv|enkät}}, {{W-|sv|rundfråga}}, {{W+|sv|opinionsundersökning}} * {{Z|tr}}: {{W+|tr|anket}}, {{W+|tr|sormaca}}, {{W+|tr|soruşturma}} {{werger-bin}} p9k0dts7ord9sbnaiynksfgfbjmd84d 6347252 6347247 2026-08-30T20:12:09Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347252 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pirsîn|Pirsîna]] ji [[xelk]]ê bo [[diyar]]kirina [[ray]]a wan li ser [[mijar]]ekê. #: {{hevmane|ku|anket|pirsname}} #* {{jêder|ku|''Şanoya Sindîbad Berî Wexerê'', Avestakurd.net, 8/2004|jêgirtin=Sebaret bi nirxandina şanoyê wek karek hunerî bi giştî û peyama wê bi taybetî, '''rapirsiyek''' ji bo bîr û rayên handeran li Duhokê encam da û tê de rêjeya 84% bi erênî nirxand.}} # [[referandûm]], [[gelpirsî]], [[dengdan]]a hemû [[milet]] li ser [[mijar]]ekê daku ew mijar bêt [[pejirandin]] yan [[red]]kirin #: {{nm|ku|Qanûna Bingehîn ya Yekîtiya Ewropayê li Frensayê û Holendayê di rapirsiyê de hat redkirin.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |rapirsiyarî |rapirsyarî |raypirsî |raypirsiyarî |raypirsyarî }} ==== Etîmolojî ==== Ji {{qertaf|ku|ray<cuda:ra><t:ray>|pirs|-î}}. ==== Werger ==== {{werger-ser|anket}} * {{Z|de}}: {{W+|de|Enquete|f}}, {{W-|de|Rundfrage}}, {{W+|de|Umfrage|f}}, {{W+|de|Untersuchung|f}}, {{W+|de|Erhebung|f}}, {{W+|de|Ermittlung}}, {{W+|de|Meinungsforschung|f|guman=erê}} * {{Z|eo}}: {{W-|eo|enketo}} * {{Z|fo}}: {{W-|fo|spurnakanning}} * {{Z|fi}}: {{W+|fi|kysely}} * {{Z|nl}}: {{W+|nl|enquête}} * {{Z|en}}: {{W+|en|poll}}, {{W+|en|survey}}, {{W+|en|referendum|guman=erê}} * {{Z|ca}}: {{W+|ca|enquesta}}, {{W+|ca|investigació}} * {{Z|pt}}: {{W+|pt|inquérito}}, {{W+|pt|investigação}}, {{W+|pt|sindicância}} * {{Z|ru}}: {{W+|ru|анкета}} * {{Z|es}}: {{W+|es|encuesta}}, {{W+|es|investigación}} * {{Z|sv}}: {{W+|sv|enkät}}, {{W-|sv|rundfråga}}, {{W+|sv|opinionsundersökning}} * {{Z|tr}}: {{W+|tr|anket}}, {{W+|tr|sormaca}}, {{W+|tr|soruşturma}} {{werger-bin}} nul7e0bgqb1asem1z34tf9a8tml8ntu helaw 0 25802 6347208 6328644 2026-08-30T16:42:41Z Wikihez 7344 /* Jê */ 6347208 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:PistHalva.jpg|thumb|[[ker|Kerek]] '''helawê'''.]] {{navdêr|ku|z=m}} # {{f|ku|şîranî}} [[şîranî|Şîraniyek]] e bi taybetî ji [[hingiv]]î û [[kuncî|kunciyên]] [[hêrayî]] tê çêkirin, [[awar]]. #: ''helawa [[gûz]]an'' #: ''helawa kunciyan'' #: ''helawa penîrî'' #: ''helawa [[tehîn]]ê'' ==== Tewandin ==== {{ku-tewîn-nav/nû|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|حه‌لاو}} ==== Formên alternatîv ==== * [[halaw]] ==== Jê ==== {{kol3|ku|cure=Jê |helawçêker |helawfiroş |helawfiroşî |helawfiroşgeh |helawfiroşxane |helawî |helawsaz |helawsazî |helawvan |helawvanî }} ==== Etîmolojî ==== Ji {{ji|ar|ku|حَلَاوَة|tr=ḥelawe<sup>t</sup>}} ji {{g|ar|حُلْو|tr=ḥulw}}, hevreha aramî {{g|arc|ܚܠܝ}} (x-l-y-: [[şîrîn]]), îbranî {{g|he|חלה}} (x-l-h-: şîrîn). Ketina "-e<sup>t</sup>" ya erebî ya nîşana [[mê]]yîtiyê ji kurdî diyardeyeke berbelav e. ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|hallvë|m}} * {{Z|de}}: {{W-|de|Halva|n}}, {{W-|de|Halwa|nt}} * {{Z|as}}: {{W-|as|হালুৱা}} * {{Z|az}}: {{W+|az|halva}} * {{Z|ba}}: {{W-|ba|хәлүә}} * {{Z|be}}: {{W-|be|халва́|m}} * {{Z|bn}}: {{W-|bn|হালুয়া}} * {{Z|bg}}: {{W-|bg|халва́|m}} * {{Z|my}}: {{W+|my|ဟလဝါ|sc=Mymr}} * {{Z|cs}}: {{W+|cs|chalva|m}} * {{Z|zh}}: *: {{Z|dng}}: {{W-|dng|халўва}}, {{W-|dng|халуван}} *: {{Z|cmn}}: {{W-|cmn|哈爾瓦|sc=Hani}}, {{W-|cmn|哈尔瓦|tr=hā'ěrwǎ|sc=Hani}} * {{Z|ar}}: {{W-|ar|حَلَاوَة طَحِيِنِيَّة|m|tr=ḥalāwa ṭaḥiyiniyya}}, {{W-|ar|حَلْوَى شَامِيَّة|m}} * {{Z|hy}}: {{W+|hy|հալվա}} * {{Z|et}}: {{W-|et|halvaa}} * {{Z|fa}}: {{W+|fa|حلوا|tr=halvâ|sc=fa-Arab}} * {{Z|fi}}: {{W+|fi|halva}} * {{Z|fr}}: {{W+|fr|halva|n}} * {{Z|ka}}: {{W-|ka|ჰალვა}} * {{Z|ha}}: {{W-|ha|alawa|m|cuda=àlāwā̀}} * {{Z|hi}}: {{W+|hi|हलवा|n}}, {{W-|hi|मोहनभीग|n}} * {{Z|nl}}: {{W-|nl|halva|n}} * {{Z|he}}: {{W+|he|חלווה|m|tr=khalvá|cuda=חַלְוָה}} * {{Z|io}}: {{W-|io|halva}} * {{Z|en}}: {{W+|en|halva}} * {{Z|it}}: {{W-|it|halva|n}} * {{Z|ja}}: {{W-|ja|ハルバ|tr=haruba}}, {{W-|ja|ハルヴァ|tr=haruva}} * {{Z|ky}}: {{W+|ky|халва|sc=Cyrl}} * {{Z|ko}}: {{W-|ko|할바}}, {{W-|ko|할와}} * {{Z|kum}}: {{W-|kum|гьалива}} * {{Z|lv}}: {{W-|lv|halva|m}} * {{Z|lt}}: {{W-|lt|chalva|m}} * {{Z|mk}}: {{W-|mk|алва|m}} * {{Z|ms}}: {{W-|ms|halwa}} * {{Z|mt}}: {{W-|mt|ħelwa tat-Tork}} * {{Z|mr}}: {{W-|mr|हलवा|sc=Deva}} * {{Z|hu}}: {{W+|hu|halva}} * {{Z|ota}}: {{W-|ota|حلوا|tr=helva}} * {{Z|ug}}: {{W+|ug|ھالۋا|sc=Arab}} * {{Z|uz}}: {{W+|uz|holva}} * {{Z|ps}}: {{W+|ps|حلوا|m|tr=halwã}} * {{Z|pl}}: {{W+|pl|chałwa|m}} * {{Z|pt}}: {{W-|pt|halvah|m}} * {{Z|kk}}: {{W-|kk|халуа|sc=Cyrl}}, {{W-|kk|қалуа|sc=Cyrl}}, {{W-|kk|алуа|sc=Cyrl}} * {{Z|ro}}: {{W+|ro|halva|m}} * {{Z|ru}}: {{W+|ru|халва́|m}} * {{Z|sh}}: *: Kirîlî: {{W-|sh|халва|m|sc=Cyrl}}, {{W-|sh|алва|m|sc=Cyrl}}, {{W-|sh|тахан халва|m|sc=Cyrl}} *: Latînî: {{W+|sh|halva|m}}, {{W+|sh|alva|m}}, {{W-|sh|tahan halva|m}} * {{Z|sk}}: {{W-|sk|chalva|m}} * {{Z|sl}}: {{W-|sl|halva|m}} * {{Z|es}}: {{W+|es|halva|n}} * {{Z|sv}}: {{W+|sv|halva|g}}, {{W-|sv|helva|g}} * {{Z|tg}}: {{W-|tg|ҳалво}} * {{Z|crh}}: {{W-|crh|elva}} * {{Z|tt}}: {{W+|tt|хәлвә}} * {{Z|tr}}: {{W+|tr|helva}}, {{W+|tr|tahin helvası}} * {{Z|tk}}: {{W-|tk|halwa}} * {{Z|ur}}: {{W-|ur|حلوہ|n|tr=halvā}} * {{Z|uk}}: {{W+|uk|халва́|m}} * {{Z|vi}}: {{W-|vi|bánh hanva}}, {{W-|vi|bánh mật}} * {{Z|yi}}: {{W-|yi|כאַלווע|m}} * {{Z|el}}: {{W+|el|χαλβάς|n}} {{werger-bin}} ppnxizbtp6xkvml5gzl75g8o4u0xow9 tekzîb 0 28798 6347214 6318641 2026-08-30T17:48:35Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347214 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[gotin|Gotin]] ku tiştek [[derew]] e; [[ragihandin]] ku tiştek ne [[rast]] e. #: {{hevmane|ku|derewandin|kezibandin|haşatî kirin}} #* {{jêder|ku|Netkurd.com, 12/2006|jêgirtin=Parlamentera Ewropayê Feleknas Uca, ku bi eslê xwe kurd û êzîdî ye, bo Netkurdê ragihand ku wê daxuyaniyên ji aliyê çapemeniya tirk ve li ser navê wê hatine belav kirin, '''tekzîb''' kirine lê çapemeniya tirk '''tekzîba''' wê naweşîne.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Jê ==== {{kol3|ku |tekzîb kirin<crz:lêker> |tekzîbkirin<crz:navdêr> |tekzîbkirî<crz:rengdêr> |tekzîbî |tekzîbker }} ==== Etîmolojî ==== Ji {{ji|ar|ku}} ==== Werger ==== {{werger-ser|tekzîb kirin}} * {{Z|de}}: {{W+|de|leugnen}}, {{W+|de|Widerruf|m|guman=erê}} * {{Z|fa}}: {{W+|fa|تکذیب}}, {{W+|fa|تکذیب|guman=erê}} * {{Z|fi}}: {{W+|fi|kiistää}} * {{Z|fr}}: {{W+|fr|nier}} * {{Z|en}}: to {{W+|en|deny}}, to [[assert]] [[that]] [[[something]] [[is]] [[not]] [[true]], {{W+|en|denial}} * {{Z|tr}}: [[tekzip]] [[etmek]], {{W+|tr|yalanlamak}}, {{W+|tr|yalanlama}} {{werger-bin}} g8mnf05kv97eoynjywcfxy4gz73r73x leşfiroş 0 30382 6347224 6346252 2026-08-30T18:13:35Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347224 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:A German prostitute's self-portrait in a brothel.jpg|150px|thumb|leşfiroşek]] {{navdêr|ku|z=}} # Kesa/ê ku bi [[pare]] [[xizmet]]ên [[seks]]ê dide xelkê. #: {{hevmane|ku|xwefiroş|fahîşe|kirûng|qehbe|orispî}} #* {{jêder|ku|jêgirtin=Rojnameya Hawlatî radigihîne ku diyardeya '''leşfiroşiyê''' (fihûşê) her ku diçe li Silêmaniyê pêşdetir diçe. Li gor îstatîstîkan hejmara '''leşfiroşan''' li vî bajarî di ser 1000 kesan re ye. <p>Berpirsên asayişê radigihînin ku ew car bi car operasyonan li hemberî '''leşfiroşiyê''' li dar dixin lê ew gelekî dûr in ji binbirrkirina vî karî. Di 2006ê asayişa Silêmaniyê di encama operasyonên xwe de qasî 40 '''leşfiroş''' girtin. Deh kes ji wan hilgirên vîrusa HIV-ê (ku pişt re dibe AIDS) bûn.|Netkurd.com, 1/2006}} ==== Bi alfabeyên din ==== * {{ku-ar|لەشفرۆش}} ==== Formên alternatîv ==== {{kol3|ku |laşfiroş |laşfroş |leşfroş }} ==== Jê ==== {{kol3|ku |leşfiroşî }} ==== Etîmolojî ==== Ji {{paş|ku|leş|-firoş}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: * {{Z|hy}}: {{W-|hy|պոռնիկ|tr=poŕnik}}, {{W-|hy|պոռնկուհի|tr=poŕnkuhi}} * {{Z|eo}}: {{W+|eo|prostituut}}, {{W+|eo|hoor}} * {{Z|fa}}: {{W-|fa|جنده|tr=cende}} * {{Z|fi}}: {{W+|fi|prostituoitu}}, {{W+|fi|huora}}, {{W+|fi|portto}}, {{W+|fi|lutka}}, {{W+|fi|lumppu}} * {{Z|fr}}: {{W|fr|prostitué|m}}, {{W|fr|prostituée|f}} * {{Z|hi}}: (veyshya) * {{Z|nl}}: {{W|nl|prostituee|f}}, {{W|nl|hoer|f}} * {{Z|he}}: {{W-|he|זונה|tr=zona}}, {{W-|he|ג׳יגולו|tr=jigolo}} * {{Z|io}}: {{W+|io|prostituco}} * {{Z|en}}: {{W|en|wapping dell|guman=erê}}, {{W|en|wapping moll|guman=erê}}, {{W|en|wapping mort|guman=erê}}[[Prostituierte]] [[:de:Prostituierte|^]], {{W|de|Hure|f}} * {{Z|en}}: {{W+|en|prostitute}}, {{W+|en|doxy}} * {{Z|it}}: [[prostituta]] [[:it:prostituta|^]] * {{Z|ja}}: {{W-|ja|売春婦|tr=baishunfu}} * {{Z|ca}}: [[prostituta]] [[:ca:prostituta|^]] * {{Z|ko}}: {{W-|ko|매춘|tr=maechun}}, {{W-|ko|매음|tr=mae-eum}} * {{Z|lt}}: {{W|lt|prostitutė|f}} * {{Z|hu}}: {{W+|hu|prostituált}}, {{W|hu|prosti|f}}, or [[örömlány]] * {{Z|no}}: {{W|no|prostituert|m}} * {{Z|pl}}: {{W|pl|prostytutka|f}}, [[męska prostytutka]] ''(male)'' * {{Z|ro}}: {{W|ro|prostituată|f}}, {{W|ro|curvă|f}}, {{W|ro|târfă|f}} * {{Z|ru}}: {{W-|ru|проститутка|tr=prostitútka}} * {{Z|sco}}: {{W|sco|siùrsach|f}}, {{W|sco|strìopach|f}} * {{Z|sk}}: {{W|sk|prostitútka#Slovak|f}}, {{W|sk|kurva#Slovak|f}}, {{W|sk|cundra#Slovak|f}} * {{Z|es}}: [[prostituta]] [[:es:prostituta|^]] * {{Z|sv}}: {{W+|sv|prostituerad}}, {{W+|sv|hora}} * {{Z|te}}: {{W-|te|వేశ్య|tr=vaeSya}} * {{Z|tr}}: {{W+|tr|orospu}}, {{W+|tr|fahişe}} * {{Z|el}}: {{W-|el|πόρνη|tr=porne}}, {{W-|el|πόρνος|tr=pornos}}, {{W-|el|πουτάνα|tr=putana}} {{werger-bin}} t0kdpos4oh98k9a7yn37z28hyyt9cj9 leşfiroşî 0 30387 6347223 6346251 2026-08-30T18:12:41Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347223 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku}} # [[xizmet|Xizmet]]ên [[seks]]ê bi [[pare]] dan xelkê, <br>[[gan]] bi [[pere]] dan. #: {{hevmane|ku|xwefiroşî|fahîşetî|fihûş|kirûngî|qehbetî|orispîtî}} #* {{jêder|ku|jêgirtin=Rojnameya Hawlatî radigihîne ku diyardeya '''leşfiroşiyê''' (fihûşê) her ku diçe li Silêmaniyê pêşdetir diçe. Li gor îstatîstîkan hejmara leşfiroşan li vî bajarî di ser 1000 kesan re ye.<p>Berpirsên asayişê radigihînin ku ew car bi car operasyonan li hemberî '''leşfiroşiyê''' li dar dixin lê ew gelekî dûr in ji binbirrkirina vî karî. Di 2006ê asayişa Silêmaniyê di encama operasyonên xwe de qasî 40 '''leşfiroş''' girtin. Deh kes ji wan hilgirên vîrusa HIV-ê (ku pişt re dibe AIDS) bûn.|Netkurd.com, 1/2006}} # {{kontrol|rêz=erê|[[ganderî]], [[forqî]], [[prostîtusyon]], [[feltetî]], [[orispîbûn]], [[qehbebûn]]}} ==== Formên alternatîv ==== {{kol3|ku |laşfiroşî |laşfroşî |leşfroşî }} ==== Etîmolojî ==== Ji {{paş|ku|leşfiroş|-î}} ''yan'' ji {{paş|ku|leş|-firoşî}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Prostitution|f}} * {{Z|cs}}: {{W+|cs|prostituce}} * {{Z|zh}}: {{W+|zh|賣淫}} * {{Z|da}}: {{W+|da|prostitution}} * {{Z|id}}: {{W+|id|pelacuran}} * {{Z|eo}}: {{W+|eo|prostituo}} * {{Z|et}}: {{W+|et|prostitutsioon}} * {{Z|fi}}: {{W+|fi|prostituutio}} * {{Z|fr}}: {{W+|fr|prostitution}} * {{Z|gd}}: {{W|gd|siùrsachd|f}}, {{W|gd|strìopachas|m}} * {{Z|nl}}: {{W+|nl|prostitutie}} * {{Z|he}}: {{W+|he|זנות}} * {{Z|he}}: {{W|he|זנונים|cuda=זְנונִים}} * {{Z|io}}: {{W+|io|prostituco}} * {{Z|en}}: {{W+|en|prostitution}}, {{W+|en|prostutition}} * {{Z|it}}: {{W+|it|prostituzione}} * {{Z|ja}}: {{W+|ja|売春}} * {{Z|ca}}: {{W+|ca|prostitució}} * {{Z|lt}}: {{W+|lt|prostitucija}} * {{Z|hu}}: {{W+|hu|prostitúció}} * {{Z|no}}: {{W+|no|prostitusjon}} * {{Z|pl}}: {{W+|pl|prostytucja}} * {{Z|pt}}: {{W+|pt|prostituição}} * {{Z|es}}: {{W+|es|prostitución}} * {{Z|sv}}: {{W+|sv|prostitution}} * {{Z|th}}: {{W+|th|การค้าประเวณี}} * {{Z|tr}}: {{W+|tr|fuhuş}}, {{W+|tr|orospuluk}}, {{W+|tr|fahişelik}} * {{Z|vi}}: {{W+|vi|mại dâm}} {{werger-bin}} mrt1si5xnddghojhn982q70bqvm3eki 6347254 6347223 2026-08-30T20:12:15Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347254 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku}} # [[xizmet|Xizmetên]] [[seks]]ê bi [[pare]] dan xelkê, <br>[[gan]] bi [[pere]] dan. #: {{hevmane|ku|xwefiroşî|fahîşetî|fihûş|kirûngî|qehbetî|orispîtî}} #* {{jêder|ku|jêgirtin=Rojnameya Hawlatî radigihîne ku diyardeya '''leşfiroşiyê''' (fihûşê) her ku diçe li Silêmaniyê pêşdetir diçe. Li gor îstatîstîkan hejmara leşfiroşan li vî bajarî di ser 1000 kesan re ye.<p>Berpirsên asayişê radigihînin ku ew car bi car operasyonan li hemberî '''leşfiroşiyê''' li dar dixin lê ew gelekî dûr in ji binbirrkirina vî karî. Di 2006ê asayişa Silêmaniyê di encama operasyonên xwe de qasî 40 '''leşfiroş''' girtin. Deh kes ji wan hilgirên vîrusa HIV-ê (ku pişt re dibe AIDS) bûn.|Netkurd.com, 1/2006}} # {{kontrol|rêz=erê|[[ganderî]], [[forqî]], [[prostîtusyon]], [[feltetî]], [[orispîbûn]], [[qehbebûn]]}} ==== Formên alternatîv ==== {{kol3|ku |laşfiroşî |laşfroşî |leşfroşî }} ==== Etîmolojî ==== Ji {{paş|ku|leşfiroş|-î}} ''yan'' ji {{paş|ku|leş|-firoşî}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Prostitution|f}} * {{Z|cs}}: {{W+|cs|prostituce}} * {{Z|zh}}: {{W+|zh|賣淫}} * {{Z|da}}: {{W+|da|prostitution}} * {{Z|id}}: {{W+|id|pelacuran}} * {{Z|eo}}: {{W+|eo|prostituo}} * {{Z|et}}: {{W+|et|prostitutsioon}} * {{Z|fi}}: {{W+|fi|prostituutio}} * {{Z|fr}}: {{W+|fr|prostitution}} * {{Z|gd}}: {{W|gd|siùrsachd|f}}, {{W|gd|strìopachas|m}} * {{Z|nl}}: {{W+|nl|prostitutie}} * {{Z|he}}: {{W+|he|זנות}} * {{Z|he}}: {{W|he|זנונים|cuda=זְנונִים}} * {{Z|io}}: {{W+|io|prostituco}} * {{Z|en}}: {{W+|en|prostitution}}, {{W+|en|prostutition}} * {{Z|it}}: {{W+|it|prostituzione}} * {{Z|ja}}: {{W+|ja|売春}} * {{Z|ca}}: {{W+|ca|prostitució}} * {{Z|lt}}: {{W+|lt|prostitucija}} * {{Z|hu}}: {{W+|hu|prostitúció}} * {{Z|no}}: {{W+|no|prostitusjon}} * {{Z|pl}}: {{W+|pl|prostytucja}} * {{Z|pt}}: {{W+|pt|prostituição}} * {{Z|es}}: {{W+|es|prostitución}} * {{Z|sv}}: {{W+|sv|prostitution}} * {{Z|th}}: {{W+|th|การค้าประเวณี}} * {{Z|tr}}: {{W+|tr|fuhuş}}, {{W+|tr|orospuluk}}, {{W+|tr|fahişelik}} * {{Z|vi}}: {{W+|vi|mại dâm}} {{werger-bin}} b8obrteb9asa59740ynybd9s4inq3pi rapelîn 0 30655 6347213 6316258 2026-08-30T17:47:08Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347213 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=ngh}} # [[rabûn]], [[hilketin]], [[bilind]] bûn #* {{bênimûne|ku}} # [[zêde]](tir) bûn, [[pirr]] bûn #* {{jêder|ku|Netkurd.com, 1/2006|jêgirtin=Bush diyar kir ku heta destpêka 2006-ê, Iraqê bi du hilbijartinan, bi referandumê û avakirina hukumeteka yekbûyî serkeftin bidest xistin, li ser vê wan perwrdekirina hêzên Iraqê berdewam kir lê hebûna eskerên xwe kêmtir kir. Vê yekê mixabin ku rê vekir şidet û teror li Iraqê bi taybetî jî li Bexdadê '''rapelike'''.}} ==== Bi alfabeyên din ==== * {{ku-ar|ڕاپه‌لین}} ==== Formên alternatîv ==== {{kol3|ku |rapelikîn |rapelkîn }} ==== Tewandin ==== : ra-pel- ==== Têkildar ==== {{kol3|ku |raperîn |rapelandin }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|pelîn}}. ==== Jê ==== {{kol3|ku |rapeliyayî }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|klettern}}, {{W+|de|hervorspringen}} * {{Z|en}}: {{W-|en|clamber up|guman=erê}} * {{Z|tr}}: {{W+|tr|atılma}}, {{W+|tr|tırmanış}}, {{W+|tr|tırmanma}}, {{W+|tr|tırmanmak}}, {{W+|tr|atılmak|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} rcp61z7obqzcmi0fo1980m5zt0wirfk 6347239 6347213 2026-08-30T18:41:09Z Balyozbot 7867 [[Special:PermanentLink/6298023|Bot]]: rêzkirina beşan 6347239 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=ngh}} # [[rabûn]], [[hilketin]], [[bilind]] bûn #* {{bênimûne|ku}} # [[zêde]](tir) bûn, [[pirr]] bûn #* {{jêder|ku|Netkurd.com, 1/2006|jêgirtin=Bush diyar kir ku heta destpêka 2006-ê, Iraqê bi du hilbijartinan, bi referandumê û avakirina hukumeteka yekbûyî serkeftin bidest xistin, li ser vê wan perwrdekirina hêzên Iraqê berdewam kir lê hebûna eskerên xwe kêmtir kir. Vê yekê mixabin ku rê vekir şidet û teror li Iraqê bi taybetî jî li Bexdadê '''rapelike'''.}} ==== Tewandin ==== : ra-pel- ==== Bi alfabeyên din ==== * {{ku-ar|ڕاپه‌لین}} ==== Formên alternatîv ==== {{kol3|ku |rapelikîn |rapelkîn }} ==== Jê ==== {{kol3|ku |rapeliyayî }} ==== Têkildar ==== {{kol3|ku |raperîn |rapelandin }} ==== Etîmolojî ==== Ji {{qertaf|ku|ra-|pelîn}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|klettern}}, {{W+|de|hervorspringen}} * {{Z|en}}: {{W-|en|clamber up|guman=erê}} * {{Z|tr}}: {{W+|tr|atılma}}, {{W+|tr|tırmanış}}, {{W+|tr|tırmanma}}, {{W+|tr|tırmanmak}}, {{W+|tr|atılmak|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} b4s5sp0iyypnm2n6dhzysq4z0h2k5h9 lîstikvan 0 31369 6347303 6326431 2026-08-31T00:31:36Z Wikihez 7344 +nimûneya bikaranînê bi amûra « [[Mediawiki:Gadget-wikt.add-examples|Nimûne zêde bike]] » (v2.0). 6347303 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=mn}} # Kesa/ê ku [[lîstin|dilîze]], kesa/ê ku [[lîstik]]ekê dike. #: {{hevmane|ku|yarîker}} #* {{jêder-websîte|ku|nivîskar=Abdulselam Akinci|websîte=Rudaw|sernav=Amedsporê bi 5 lîstikvanên nû şov kir|url=https://www.rudaw.net/kurmanci/categories/sport/1304045|tarîx=2026-08-11|jêgirtin='''Lîstikvanên''' nû yên Amedsporê soza serkeftinê da alîgiran.}} # [[zarîker]], [[şanovan]], [[aktor]] yan [[aktrîs]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê û nêr}} ==== Formên alternatîv ==== * [[lehîstikvan]] * [[leyîstikvan]] * [[lîztikvan]] ==== Jê ==== * [[lîstikvanî]] ==== Etîmolojî ==== Ji {{paş|ku|lîstik|-van}}, {{yekser|tr|ku|oyuncu|hûr=1}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Akteur}} {{n}}, {{W|de|Darsteller}} {{n}}, {{W|de|Darstellerin}}, {{W|de|Schauspieler}} {{n}}, {{W|de|Schauspielerin}} {{mê}}, {{W|de|Spieler}} {{n}} * {{Z|cs}}: {{W|cs|hráč}} {{n}} * {{Z|zh}}: *: {{Z|cmn}}: {{W|cmn|運動員|sc=Hani}}, {{W|cmn|运动员|tr=yùndòngyuán}}, {{W|cmn|競賽者|sc=Hani}}, {{W|cmn|竞赛者|tr=jìngsàizhe}}, {{W|cmn|選手|sc=Hani}}, {{W|cmn|选手|tr=xuǎnshǒu}} * {{Z|da}}: {{W|da|spiller|c}} * {{Z|ar}}: {{W|ar|لاعب|tr=laa3ib}} {{n}}, {{W|ar|ممثل|guman=erê}} * {{Z|fa}}: {{W|fa|آکتور}}, {{W|fa|بازیگر}}, {{W|fa|ژیرمند}}, {{W|fa|ژیرنده}}, {{W|fa|هنرپیشه}} * {{Z|fi}}: {{W|fi|pelaaja}} * {{Z|fr}}: {{W|fr|joueur}} {{n}} * {{Z|gl}}: {{W|gl|xogador|xs=Galician}} * {{Z|nl}}: {{W|nl|speler}} {{n}} * {{Z|en}}: {{W|en|player}}, {{W|en|kitsch}}, {{W|en|actor m.}}, {{W|en|actress f.}} * {{Z|it}}: {{W|it|giocatore}} * {{Z|ja}}: {{W|ja|選手|tr=せんしゅ, senshu}} * {{Z|no}}: {{W|no|spiller}} {{n}} * {{Z|pl}}: {{W|pl|gracz}} {{n}}, {{W|pl|zawodnik}} {{n}} * {{Z|pt}}: {{W|pt|jogador}} * {{Z|ro}}: {{W|ro|jucător}} * {{Z|ru}}: {{W|ru|игрок}} {{n}}, {{W|ru|спортсмен|m|tr=sportsmén}} * {{Z|sh}}: {{W|sh|igrač}} {{n}}, {{W|sh|igračica}} {{mê}} * {{Z|es}}: {{W|es|jugador}} {{n}}, {{W|es|jugadora}} {{mê}} * {{Z|sw}}: {{W|sw|mchezaji|xs=Swahili}} * {{Z|sv}}: {{W|sv|spelare|c}} * {{Z|tr}}: {{W|tr|oyuncu}}, {{W|tr|oyunbaz}} * {{Z|el}}: {{W|el|παίκτης|tr=paíktis}} {{n}}, {{W|el|παίκτρια|tr=paíkttia}} {{mê}} {{werger-bin}} 5z3zjwb5zfa512x58c8tepysweywsvl 6347304 6347303 2026-08-31T00:32:47Z Wikihez 7344 /* Etîmolojî */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347304 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=mn}} # Kesa/ê ku [[lîstin|dilîze]], kesa/ê ku [[lîstik]]ekê dike. #: {{hevmane|ku|yarîker}} #* {{jêder-websîte|ku|nivîskar=Abdulselam Akinci|websîte=Rudaw|sernav=Amedsporê bi 5 lîstikvanên nû şov kir|url=https://www.rudaw.net/kurmanci/categories/sport/1304045|tarîx=2026-08-11|jêgirtin='''Lîstikvanên''' nû yên Amedsporê soza serkeftinê da alîgiran.}} # [[zarîker]], [[şanovan]], [[aktor]] yan [[aktrîs]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê û nêr}} ==== Formên alternatîv ==== * [[lehîstikvan]] * [[leyîstikvan]] * [[lîztikvan]] ==== Jê ==== * [[lîstikvanî]] ==== Etîmolojî ==== {{yekser|tr|ku|oyuncu}}. {{anlz|ku|lîstik|-van}}, ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Akteur}} {{n}}, {{W|de|Darsteller}} {{n}}, {{W|de|Darstellerin}}, {{W|de|Schauspieler}} {{n}}, {{W|de|Schauspielerin}} {{mê}}, {{W|de|Spieler}} {{n}} * {{Z|cs}}: {{W|cs|hráč}} {{n}} * {{Z|zh}}: *: {{Z|cmn}}: {{W|cmn|運動員|sc=Hani}}, {{W|cmn|运动员|tr=yùndòngyuán}}, {{W|cmn|競賽者|sc=Hani}}, {{W|cmn|竞赛者|tr=jìngsàizhe}}, {{W|cmn|選手|sc=Hani}}, {{W|cmn|选手|tr=xuǎnshǒu}} * {{Z|da}}: {{W|da|spiller|c}} * {{Z|ar}}: {{W|ar|لاعب|tr=laa3ib}} {{n}}, {{W|ar|ممثل|guman=erê}} * {{Z|fa}}: {{W|fa|آکتور}}, {{W|fa|بازیگر}}, {{W|fa|ژیرمند}}, {{W|fa|ژیرنده}}, {{W|fa|هنرپیشه}} * {{Z|fi}}: {{W|fi|pelaaja}} * {{Z|fr}}: {{W|fr|joueur}} {{n}} * {{Z|gl}}: {{W|gl|xogador|xs=Galician}} * {{Z|nl}}: {{W|nl|speler}} {{n}} * {{Z|en}}: {{W|en|player}}, {{W|en|kitsch}}, {{W|en|actor m.}}, {{W|en|actress f.}} * {{Z|it}}: {{W|it|giocatore}} * {{Z|ja}}: {{W|ja|選手|tr=せんしゅ, senshu}} * {{Z|no}}: {{W|no|spiller}} {{n}} * {{Z|pl}}: {{W|pl|gracz}} {{n}}, {{W|pl|zawodnik}} {{n}} * {{Z|pt}}: {{W|pt|jogador}} * {{Z|ro}}: {{W|ro|jucător}} * {{Z|ru}}: {{W|ru|игрок}} {{n}}, {{W|ru|спортсмен|m|tr=sportsmén}} * {{Z|sh}}: {{W|sh|igrač}} {{n}}, {{W|sh|igračica}} {{mê}} * {{Z|es}}: {{W|es|jugador}} {{n}}, {{W|es|jugadora}} {{mê}} * {{Z|sw}}: {{W|sw|mchezaji|xs=Swahili}} * {{Z|sv}}: {{W|sv|spelare|c}} * {{Z|tr}}: {{W|tr|oyuncu}}, {{W|tr|oyunbaz}} * {{Z|el}}: {{W|el|παίκτης|tr=paíktis}} {{n}}, {{W|el|παίκτρια|tr=paíkttia}} {{mê}} {{werger-bin}} f86jcoe5oqtgio5a87o79b9gvfe0jfm 6347305 6347304 2026-08-31T00:32:54Z Wikihez 7344 /* Etîmolojî */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347305 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=mn}} # Kesa/ê ku [[lîstin|dilîze]], kesa/ê ku [[lîstik]]ekê dike. #: {{hevmane|ku|yarîker}} #* {{jêder-websîte|ku|nivîskar=Abdulselam Akinci|websîte=Rudaw|sernav=Amedsporê bi 5 lîstikvanên nû şov kir|url=https://www.rudaw.net/kurmanci/categories/sport/1304045|tarîx=2026-08-11|jêgirtin='''Lîstikvanên''' nû yên Amedsporê soza serkeftinê da alîgiran.}} # [[zarîker]], [[şanovan]], [[aktor]] yan [[aktrîs]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav/nû|mê û nêr}} ==== Formên alternatîv ==== * [[lehîstikvan]] * [[leyîstikvan]] * [[lîztikvan]] ==== Jê ==== * [[lîstikvanî]] ==== Etîmolojî ==== {{yekser|tr|ku|oyuncu}}. {{anlz|ku|lîstik|-van}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Akteur}} {{n}}, {{W|de|Darsteller}} {{n}}, {{W|de|Darstellerin}}, {{W|de|Schauspieler}} {{n}}, {{W|de|Schauspielerin}} {{mê}}, {{W|de|Spieler}} {{n}} * {{Z|cs}}: {{W|cs|hráč}} {{n}} * {{Z|zh}}: *: {{Z|cmn}}: {{W|cmn|運動員|sc=Hani}}, {{W|cmn|运动员|tr=yùndòngyuán}}, {{W|cmn|競賽者|sc=Hani}}, {{W|cmn|竞赛者|tr=jìngsàizhe}}, {{W|cmn|選手|sc=Hani}}, {{W|cmn|选手|tr=xuǎnshǒu}} * {{Z|da}}: {{W|da|spiller|c}} * {{Z|ar}}: {{W|ar|لاعب|tr=laa3ib}} {{n}}, {{W|ar|ممثل|guman=erê}} * {{Z|fa}}: {{W|fa|آکتور}}, {{W|fa|بازیگر}}, {{W|fa|ژیرمند}}, {{W|fa|ژیرنده}}, {{W|fa|هنرپیشه}} * {{Z|fi}}: {{W|fi|pelaaja}} * {{Z|fr}}: {{W|fr|joueur}} {{n}} * {{Z|gl}}: {{W|gl|xogador|xs=Galician}} * {{Z|nl}}: {{W|nl|speler}} {{n}} * {{Z|en}}: {{W|en|player}}, {{W|en|kitsch}}, {{W|en|actor m.}}, {{W|en|actress f.}} * {{Z|it}}: {{W|it|giocatore}} * {{Z|ja}}: {{W|ja|選手|tr=せんしゅ, senshu}} * {{Z|no}}: {{W|no|spiller}} {{n}} * {{Z|pl}}: {{W|pl|gracz}} {{n}}, {{W|pl|zawodnik}} {{n}} * {{Z|pt}}: {{W|pt|jogador}} * {{Z|ro}}: {{W|ro|jucător}} * {{Z|ru}}: {{W|ru|игрок}} {{n}}, {{W|ru|спортсмен|m|tr=sportsmén}} * {{Z|sh}}: {{W|sh|igrač}} {{n}}, {{W|sh|igračica}} {{mê}} * {{Z|es}}: {{W|es|jugador}} {{n}}, {{W|es|jugadora}} {{mê}} * {{Z|sw}}: {{W|sw|mchezaji|xs=Swahili}} * {{Z|sv}}: {{W|sv|spelare|c}} * {{Z|tr}}: {{W|tr|oyuncu}}, {{W|tr|oyunbaz}} * {{Z|el}}: {{W|el|παίκτης|tr=paíktis}} {{n}}, {{W|el|παίκτρια|tr=paíkttia}} {{mê}} {{werger-bin}} juqzgzvzq54b4cpbh99bv55qm48mdly secere 0 34130 6347221 6317178 2026-08-30T18:01:12Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347221 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[darav]], [[binemal]], [[dûnde]], [[silale]], [[zuryet]], [[ûcax]], [[malbat]], [[ajar]], [[komrig]], [[eylet]], [[dol]], [[şecere]] #* {{jêder|ku|jêgirtin=Serokê partiya MHP-ê Devlet Bahçeli van rojan pir bi ser AKP-ê de diçe û wê bi piştgiriya serokê Kurdistanê Mesûd Barzanî û başûrê Kurdistanê tawanbar dike. Dewlet Bahçelî êrişî Mir Dengir Mehmet Firatê arîkarê serokwezîrê tirkan Recep Tayyip Erdoganî kir û got ew li gor “'''secereya''' bapîrê xwe hereket dike”. Mir Dengir Mehmet Firat kurd e û behsa serokkomariya wî ji bo Tirkiyeyê têt kirin.|Nefel.com, 3/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Formên alternatîv ==== {{kol3|ku |sulale }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|tr=şecere|t=[[dar]]}}. ==== Bide ber ==== {{kol3|ku |silal }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Abkömmling|m}}, {{W+|de|Nachkomme|m}} * {{Z|ar}}: {{W-|ar|شجرة النسب|guman=erê}} * {{Z|fi}}: {{W+|fi|jälkeläinen}} * {{Z|fr}}: {{W+|fr|progéniture}}, {{W+|fr|lignée}} * {{Z|en}}: {{W+|en|descendent}}, {{W+|en|progeny}}, {{W+|en|offspring}} * {{Z|it}}: {{W+|it|progenie}} * {{Z|pt}}: {{W+|pt|progênie}} * {{Z|ru}}: {{W+|ru|потомок}}, {{W+|ru|отпрыск}} * {{Z|es}}: {{W+|es|descendencia}}, {{W-|es|progenitura}}, {{W+|es|progenie}} * {{Z|sv}}: {{W+|sv|avkomma}}, {{W+|sv|efterkommande}} * {{Z|tr}}: {{W+|tr|zürriyet}}, {{W+|tr|soy}}, {{W+|tr|sülale}} {{werger-bin}} c8gtb1e5tttm6frnuea4jr4rcrrhnvf qebîle 0 34522 6347222 6326485 2026-08-30T18:12:06Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347222 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[hoz]], [[êl]], [[eşîr]] #* {{bêmînak|ku}} # [[hoz]], [[kom]], [[yekîtî]] #* {{J:Mem û Zîn:1692|jêgirtin=Ciwamêrî û hîmmet û sexawet<br>Mêrînî û xîret û celadet<br>Ew xetme ji bo '''qebîlê''' Ekrad<br>Wan dane bi şîr û hîmmetê dad<br>Hindî ji şeca’etê xeyûr in<br>Ew çende ji minnetê nefûr in}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Jê ==== {{kol3|ku |qebîleyî }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|قَبِيلَة}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Sippe}} {{mê}}, {{W+|de|Stamm}} {{n}}, {{W+|de|Volksgruppe}} * {{Z|fa}}: {{W+|fa|قبیله}}, {{W+|fa|قبیله}} * {{Z|en}}: {{W+|en|tribe}} * {{Z|tr}}: {{W+|tr|kabile}}, {{W+|tr|klan}} {{werger-bin}} gcjrwgmj4chkw29bt6nrz607jnnlu09 6347251 6347222 2026-08-30T20:11:38Z Wikihez 7344 +Bi alfabeyên din (DefSideBoxes) 6347251 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[hoz]], [[êl]], [[eşîr]] #* {{bêmînak|ku}} # [[hoz]], [[kom]], [[yekîtî]] #* {{J:Mem û Zîn:1692|jêgirtin=Ciwamêrî û hîmmet û sexawet<br>Mêrînî û xîret û celadet<br>Ew xetme ji bo '''qebîlê''' Ekrad<br>Wan dane bi şîr û hîmmetê dad<br>Hindî ji şeca’etê xeyûr in<br>Ew çende ji minnetê nefûr in}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Jê ==== {{kol3|ku |qebîleyî }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|قَبِيلَة}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Sippe}} {{mê}}, {{W+|de|Stamm}} {{n}}, {{W+|de|Volksgruppe}} * {{Z|fa}}: {{W+|fa|قبیله}}, {{W+|fa|قبیله}} * {{Z|en}}: {{W+|en|tribe}} * {{Z|tr}}: {{W+|tr|kabile}}, {{W+|tr|klan}} {{werger-bin}} ==== Bi alfabeyên din ==== * {{ku-ar|قەبیلە}} t32al9pud5lgokvyirzrsvg7g2n9nx5 6347255 6347251 2026-08-30T20:12:21Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347255 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[hoz]], [[êl]], [[eşîr]] #* {{bêmînak|ku}} # [[hoz]], [[kom]], [[yekîtî]] #* {{J:Mem û Zîn:1692|jêgirtin=Ciwamêrî û hîmmet û sexawet<br>Mêrînî û xîret û celadet<br>Ew xetme ji bo '''qebîlê''' Ekrad<br>Wan dane bi şîr û hîmmetê dad<br>Hindî ji şeca’etê xeyûr in<br>Ew çende ji minnetê nefûr in}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Bi alfabeyên din ==== * {{ku-ar|قەبیلە}} ==== Jê ==== {{kol3|ku |qebîleyî }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|قَبِيلَة}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Sippe}} {{mê}}, {{W+|de|Stamm}} {{n}}, {{W+|de|Volksgruppe}} * {{Z|fa}}: {{W+|fa|قبیله}}, {{W+|fa|قبیله}} * {{Z|en}}: {{W+|en|tribe}} * {{Z|tr}}: {{W+|tr|kabile}}, {{W+|tr|klan}} {{werger-bin}} seihcvzal2yqo3a6dzzphgpr94zkms4 pêkhate 0 35780 6347218 6325368 2026-08-30T17:58:16Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347218 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # Hemû tiştên ku di nav [[tişt]]ekî de hene; hemû tiştên ku tiştek jê çêbûye. #* {{jêder-kovar|ku|jêgirtin=Di sedsala dawîn de texrîbata li ser erdnîgarî, rih û derûniya kurdan hatiye kirin bi demê re bûye perçeyek ji bîra hevpar a kurdan ku dîroka nêzîk, serpêhatiyên takekesî, hişmendiya zimên a têkçûyî, bişaftinên pirr-alî, karesatên mezin '''pêkhateyên''' vê texrîbata domdirêj in.|kovar=Wêje û Rexne|nivîskar=[[w:Ömer Delikaya|Ömer Delikaya]]|sernav=Bîra Hevpar û Serpêhatiyeke Trawmatîk di Çinara Mihemed Ronahî de|hejmar=4|r=173}} # Hemû [[meriv]]ên yan [[milet]]ên ku li [[welat]]ekî yan [[herêm]]ekê [[jîn|dijîn]]. #: {{nm|ku|'''Pêkhateyên''' serekî yên Iraqê ereb û kurd in.}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Formên alternatîv ==== {{kol3|ku |pêkhat }} ==== Etîmolojî ==== [[pêk hatin]] ==== Bide ber ==== {{kol3|ku |pirpêkhate }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Gebilde|m|guman=erê}} * {{Z|fa}}: {{W+|fa|ساختار}} * {{Z|en}}: {{W+|en|constituent}}, {{W+|en|structure}}, {{W+|en|ingredients|guman=erê}}, {{W+|en|formation|guman=erê}}, {{W+|en|component|guman=erê}}, {{W-|en|hîdrokarbon|guman=erê}}, {{W+|en|hydrocarbon|guman=erê}}, {{W+|en|component}} * {{Z|tr}}: {{W+|tr|bileşen}}, {{W+|tr|öğe}}, {{W-|tr|bileşiği meydana getiren}} {{werger-bin}} 0ikj8j6c845z7xegd7sfs60gv02doa4 danîşan 0 36549 6347215 6304586 2026-08-30T17:50:16Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347215 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # Tişta/ê tiştek jê [[diyar]] dibe; tişta/ê mirov tiştekê/î pê [[nasîn|dinase]] yan [[zanîn|dizane]]. #: {{hevmane|ku|îşaret|remz|sembol}} #* {{bênimûne|ku}} # [[delîl]], [[emare]], [[elamet]] #* {{jêder|ku|jg=Ger zayend di kurmanciyê de têk biçe, dê encamên wî çî bin? Dê ev zarave hêsantir an jî zehmettir bibe? Dema ku di kurmanciya devkî de ev guherîn diqewimin, em baş dizanin ku li alîyê din, ev zarave gihiştiye qonaxeke standardbûnê. Bi hezaran berhemên edebî ku bi kurmancî çap bûne '''danîşanên''' vê standardbûnê ne. Lê ziman di her du kodên devkî û nivîskiyê de pêşve diçe. Ji nebûna perwerdeyê û dezgehên neteweyî, ev her du kod îro ji hev dûr ketine û her yekê wan bi aliyek ve dimeşe. Di vê pêvajoyê de, biryar ya axifêrên zimanan e.|Salih Akin, ''Guherînên di Zaravayê Kurmanciyê de: Pirsgireka Zayendê'', Toplum ve Kuram Dergisi, hj. 3, 2010}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Jê ==== {{kol3|ku |danîşanî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W+|tr|delil}}, {{W+|tr|gösterim}}, {{W+|tr|gösterge}}, {{W+|tr|işaret}}, {{W+|tr|emare}} {{werger-bin}} nswga5x5chymt7a10h0udvktq33t4ug wecîze 0 39128 6347243 6347116 2026-08-30T18:45:49Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347243 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[aforîzm]], [[pend]], [[lakonîk]], [[şîret]], [[epîtaf]], [[maksîm]], [[adaj]], [[apoftem]] #* {{jêder-websîte|ku|nivîskar=w:Yaqob Tilermenî|websîte=diyarname.com|sernav=Ma matematîk jî me dixapîne?|url=https://www.diyarname.com/nivis/ma-matematik-ji-me-dixapine_13116|tarîx=25.08.2026|jêgirtin={{...}}(Rêyeke bi hezar kîlometreyî, bi gaveke biçûk dest pê dike.)”. Li gora matematîkê 1000 km dikare bi xwelivandinê jî dest pê bike. Îro ev gotin wekî '''vecîzekê''' di devê gelek kesan de ye.}} #* {{jêder|ku|Sernavê berhevokekê ku Abdulkadir Bîngol wergerandiye, Nefel.com, 7/2009|jêgirtin='''Wecîzeyên''' ustad Bedîûzzeman Mele Seîdê Kurdî}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Etîmolojî ==== Ji {{ji|ar|ku}} ==== Bide ber ==== {{kol3|ku |mucîze }} ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W-|af|aforisme}} * {{Z|de}}: {{W+|de|Aphorismus|m}}, {{W-|de|Gedankensplitter}}, {{W-|de|Sinnspruch}}, {{W+|de|Spruch|m}}, {{W+|de|aphoristisch|guman=erê}}, {{W+|de|bündig|guman=erê}}, {{W+|de|knapp|guman=erê}}, {{W+|de|lakonisch|guman=erê}}, {{W+|de|lapidar|guman=erê}}, {{W+|de|Apophthegma|m|guman=erê}}, {{W-|de|Lakonie|f|guman=erê}} * {{Z|eo}}: {{W+|eo|aforismo}} * {{Z|fi}}: {{W+|fi|mietelause}}, {{W+|fi|aforismi}} * {{Z|fr}}: {{W+|fr|aphorisme}} * {{Z|nl}}: {{W+|nl|aforisme}}, {{W+|nl|spreuk}}, {{W-|nl|kernspreuk}} * {{Z|io}}: {{W+|io|aforismo}} * {{Z|en}}: {{W+|en|aphorism}}, {{W+|en|apothegm}} * {{Z|is}}: {{W+|is|spakmæli}} * {{Z|ca}}: {{W+|ca|aforisme}} * {{Z|hu}}: {{W+|hu|aforizma}} * {{Z|pt}}: {{W+|pt|aforismo}}, {{W-|pt|prolóquio}} * {{Z|es}}: {{W+|es|aforismo}} * {{Z|tr}}: {{W+|tr|aforizm}}, {{W+|tr|özdeyiş}}, {{W+|tr|özlü söz}}, {{W-|tr|ulusöz}}, {{W+|tr|lakonik}}, {{W+|tr|öz deyiş}}, {{W+|tr|vecize}}, {{W+|tr|hikmet}}, {{W+|tr|veciz|guman=erê}} {{werger-bin}} 7j38zu4j9hv8ifyezo95dpm8kvjl5qj zirnazîq 0 39712 6347185 6326551 2026-08-30T13:55:39Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347185 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:SeesawWithKids_wb.png|thumb|250px|zirnazîqek]] {{navdêr|ku|z=m}} # [[dar|Dar]]ek [[dirêj]] e ku du kes her yek li serekî [[siwar]] dibe û [[geh]] yek [[bilind]] dibe û yê din [[nizm]] û geh jî [[berevajî]]. #: {{hevmane|ku|qirnaqoz|çîrneçov|helezek|denglekişo|qaqleqûz|zîqûzelaq|zîqûzir|sîqûsir|darînqoz|qirqosan|cînceq|memeqîz|hindirhop|silimsîq|terazûmîzan|hildilhok|hêlanok|hêlhêlanê|tiringûzan}} #* {{jêder-websîte|ku|jêgirtin=Ferîdê hecî Casim heta ku xwendegeha navîn dixwend bi giyanî xwe li tirkî girêdida, salên wî yên li Diyarbekirê jî wisa derbas bûn. Demek di pey çûyîna zanîngehê (li metropolê) me bihîst ku Ferîd abê 180 dece vegeriyaye, bi temamî xwe li kurdî girêdaye û bi ser de devkî, nivîskî, govendkî di vê têkoşînê de bêwestan havilkar e. Lê çi heye gava di westana havînan de tê seredana mala bavê xwe, wek ku li aliyek '''zirnazîq'''ê (tirki; tahteravallı, îngîlîzî; seesaw) siwarbûbe geh radibe jorê geh dadikeve jêrê. Bêguman jor rêngdêriya “türk aydını” û jêr jî damarê kurdewarî, an jî bi gotinek dinê hê bi temamî “nekarîna tirk bûyînê” ye. Di vê ya dawiyê de jî bersîva wî tim di berîkê de amade ye: “Kürdüm amma ilkel kürt değilim” (kurd im, lê ne yê hovî me).|nivîskar=[[w:Rojen Barnas|Rojen Barnas]]|sernav=[[meqletîz|Meqletîz]]|websîte=Netkurd.com|sal=6/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din==== * {{ku-ar|زرنازیق}} ==== Formên alternatîv ==== {{kol3|ku |çirnecoq |zirnazoq |zirnezîq |zirnezoq |zirnaçox }} ==== Jê ==== {{kol3|ku |zirnazîqanê |zirnazîqî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Wippe}} {{mê}}, {{W+|de|Schaukel}} {{mê}}, {{W+|de|Schaukelbrett}} {{nt}} * {{Z|zh}}: {{W-|zh|蹺蹺板}} * {{Z|fa}}: {{W+|fa|الاکلنگ}} * {{Z|fr}}: {{W+|fr|tapecul}} {{n}}, {{W+|fr|balançoire}} {{mê}} * {{Z|nl}}: {{W+|nl|wipwap}} * {{Z|he}}: {{W-|he|נדנדה מאוזנת}} * {{Z|en}}: {{W+|en|seesaw}} * {{Z|ja}}: {{W-|ja|シーソー}} * {{Z|ko}}: {{W-|ko|널|tr=neol}}, {{W-|ko|널뛰기|tr=neol-ttwigi}} * {{Z|hu}}: {{W-|hu|libikóka}}, {{W+|hu|mérleghinta}} * {{Z|pl}}: {{W-|pl|huśtawka na desce}} * {{Z|pt}}: {{W+|pt|balancé}}, {{W+|pt|gangorra}} * {{Z|sv}}: {{W-|sv|gungbräda}} * {{Z|th}}: {{W+|th|กระดานหก}} * {{Z|tr}}: {{W-|tr|tahteravallı}}, {{W-|tr|tahtarevali}}, {{W+|tr|tahterevalli}} * {{Z|el}}: {{W+|el|τραμπάλα}} {{werger-bin}} 4z64jqpk7u1xqm1ulgng20oc2ydaho9 6347191 6347185 2026-08-30T15:12:14Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir, Valahiya beşan rast kir.) 6347191 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:SeesawWithKids_wb.png|thumb|250px|zirnazîqek]] {{navdêr|ku|z=m}} # [[dar|Darek]] [[dirêj]] e ku du kes her yek li serekî [[siwar]] dibe û [[geh]] yek [[bilind]] dibe û yê din [[nizm]] û geh jî [[berevajî]]. #: {{hevmane|ku|qirnaqoz|çîrneçov|helezek|denglekişo|qaqleqûz|zîqûzelaq|zîqûzir|sîqûsir|darînqoz|qirqosan|cînceq|memeqîz|hindirhop|silimsîq|terazûmîzan|hildilhok|hêlanok|hêlhêlanê|tiringûzan}} #* {{jêder-websîte|ku|jêgirtin=Ferîdê hecî Casim heta ku xwendegeha navîn dixwend bi giyanî xwe li tirkî girêdida, salên wî yên li Diyarbekirê jî wisa derbas bûn. Demek di pey çûyîna zanîngehê (li metropolê) me bihîst ku Ferîd abê 180 dece vegeriyaye, bi temamî xwe li kurdî girêdaye û bi ser de devkî, nivîskî, govendkî di vê têkoşînê de bêwestan havilkar e. Lê çi heye gava di westana havînan de tê seredana mala bavê xwe, wek ku li aliyek '''zirnazîq'''ê (tirki; tahteravallı, îngîlîzî; seesaw) siwarbûbe geh radibe jorê geh dadikeve jêrê. Bêguman jor rêngdêriya “türk aydını” û jêr jî damarê kurdewarî, an jî bi gotinek dinê hê bi temamî “nekarîna tirk bûyînê” ye. Di vê ya dawiyê de jî bersîva wî tim di berîkê de amade ye: “Kürdüm amma ilkel kürt değilim” (kurd im, lê ne yê hovî me).|nivîskar=[[w:Rojen Barnas|Rojen Barnas]]|sernav=[[meqletîz|Meqletîz]]|websîte=Netkurd.com|sal=6/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|زرنازیق}} ==== Formên alternatîv ==== {{kol3|ku |çirnecoq |zirnazoq |zirnezîq |zirnezoq |zirnaçox }} ==== Jê ==== {{kol3|ku |zirnazîqanê |zirnazîqî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Wippe}} {{mê}}, {{W+|de|Schaukel}} {{mê}}, {{W+|de|Schaukelbrett}} {{nt}} * {{Z|zh}}: {{W-|zh|蹺蹺板}} * {{Z|fa}}: {{W+|fa|الاکلنگ}} * {{Z|fr}}: {{W+|fr|tapecul}} {{n}}, {{W+|fr|balançoire}} {{mê}} * {{Z|nl}}: {{W+|nl|wipwap}} * {{Z|he}}: {{W-|he|נדנדה מאוזנת}} * {{Z|en}}: {{W+|en|seesaw}} * {{Z|ja}}: {{W-|ja|シーソー}} * {{Z|ko}}: {{W-|ko|널|tr=neol}}, {{W-|ko|널뛰기|tr=neol-ttwigi}} * {{Z|hu}}: {{W-|hu|libikóka}}, {{W+|hu|mérleghinta}} * {{Z|pl}}: {{W-|pl|huśtawka na desce}} * {{Z|pt}}: {{W+|pt|balancé}}, {{W+|pt|gangorra}} * {{Z|sv}}: {{W-|sv|gungbräda}} * {{Z|th}}: {{W+|th|กระดานหก}} * {{Z|tr}}: {{W-|tr|tahteravallı}}, {{W-|tr|tahtarevali}}, {{W+|tr|tahterevalli}} * {{Z|el}}: {{W+|el|τραμπάλα}} {{werger-bin}} 2mxpduhegrq6an9pvh9ue7xi6e22frw çexer 0 39713 6347216 6321913 2026-08-30T17:53:02Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347216 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[patîka]], [[rêk]], [[pêleng]], [[rêşivan]], [[şoprê]], [[xaçerêk]], [[şifîle]], [[şivanrêk]], [[şiverêk]], [[şiverê]], [[şivîl]], [[şivîle]] #* {{jêder-websîte|ku|jêgirtin=Mihemedê Îsmet efendî jî hingê çûbû Îstenbolê; camêr li riya tirkbûyînê '''çexera''' xwe vekir, ji xwe re xanimeka tirkbûyî anî û di riya xwe de bêşewişîn bi ser ket. Niha wek malbatek tirk li jiyanê dikudîne. Aferîn! Yekrûyîtî timî ji durûyîtiyê qenctir e.|nivîskar=Rojen Barnas|sernav=[[meqletîz|Meqletîz]]|websîte=Netkurd.com|sal=6/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bide ber ==== {{kol3|ku |zirnezîq }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Schaukel|f}}, {{W+|de|Wippe|f}} * {{Z|fa}}: {{W+|fa|پا}}, {{W-|fa|رد پا}}, {{W-|fa|اثر پا}} * {{Z|en}}: {{W+|en|seesaw}}, {{W+|en|teeter-totter}} * {{Z|tr}}: {{W+|tr|patika}} {{werger-bin}} 74h83plcgy3laqafxkt19w70h49hh52 6347238 6347216 2026-08-30T18:41:06Z Balyozbot 7867 [[Special:PermanentLink/6298023|Bot]]: rêzkirina beşan 6347238 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[patîka]], [[rêk]], [[pêleng]], [[rêşivan]], [[şoprê]], [[xaçerêk]], [[şifîle]], [[şivanrêk]], [[şiverêk]], [[şiverê]], [[şivîl]], [[şivîle]] #* {{jêder-websîte|ku|jêgirtin=Mihemedê Îsmet efendî jî hingê çûbû Îstenbolê; camêr li riya tirkbûyînê '''çexera''' xwe vekir, ji xwe re xanimeka tirkbûyî anî û di riya xwe de bêşewişîn bi ser ket. Niha wek malbatek tirk li jiyanê dikudîne. Aferîn! Yekrûyîtî timî ji durûyîtiyê qenctir e.|nivîskar=Rojen Barnas|sernav=[[meqletîz|Meqletîz]]|websîte=Netkurd.com|sal=6/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== {{kol3|ku |zirnezîq }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Schaukel|f}}, {{W+|de|Wippe|f}} * {{Z|fa}}: {{W+|fa|پا}}, {{W-|fa|رد پا}}, {{W-|fa|اثر پا}} * {{Z|en}}: {{W+|en|seesaw}}, {{W+|en|teeter-totter}} * {{Z|tr}}: {{W+|tr|patika}} {{werger-bin}} 06ekoic1ubu78wvqyowpu9w148xwitq teres 0 40064 6347179 6346982 2026-08-30T13:46:05Z Wikihez 7344 [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347179 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku}} # Kesa/ê ku [[leşfiroşî|leşfiroşiyê]] di navbera du kesan de dike, <br>kesa/ê ku [[leşfiroş]]an [[gihandin|digihîne]] [[leşkir]]an. #: {{hevmane|ku|pêzeweng|qewad|qebrax|desnîk|godoş|astîk}} #* {{bêmînak|ku}} # [[dijûn]]ek e #* {{bêmînak|ku}} # [[kes]]ê/a ji [[tirs]]ê [[gav]] [[paş]] avêtiye #* {{bêmînak|ku}} # {{mane?|ku}} #* {{jêder|ku|jêgirtin=Dê hingî em li ser Tirko û sîyaseta Tirko dinivîsin, mû bi zimanê me ve şîn hat, gû bi zimanê me de hat. Bi telaq û namûs, tilîyên me hew dilivin. Gerandina pênûsê bi wan zor tê. Lê hezar û nizanim çi qas mixabin, dawîya qebhet, bobelet, '''teresî''' û minafiqîyên Tirko nayê.|Lotikxane.com, 6/2007}} ==== Formên alternatîv ==== {{kol3|ku |terez }} ==== Jê ==== {{kol3|ku|cure=Jê |teres bûn<crz:lêker> |teres kirin<crz:lêker> |teresbûn<crz:navdêr> |tereskirin<crz:navdêr> |teresbûyî<crz:rengdêr> |tereskirî<crz:rengdêr> |teresî |teresîtî |terestî |teresbav }} ==== Etîmolojî ==== Ji berêtir {{jinûvesazî |terse}} hevrreha {{hv|fa|ترسا|tr=tersa|w=mesiyanî, gawir, [[file]]}} û {{hv|pal|tr=tersag|w=gawir, fileh, mesiyanî}}; ji {{paş|ku|tirsîn|-e}} ango "xwedêtirs". Hevrreha {{hv|az|-}} û {{hv|tr|ters}} û [[vam]] bûye {{hv|ota|ترس|tr=teres}}. Ramana ji ''mesihî'' > ''jinfiroş; deyûs'' dibe ji bizaveka dîrokî hatibe kû Fileh jinên xwe difroştin yan ji aliyê Kurdan vî awayî dihatin dîtin. Bo viya bide ber {{hv|ar|دیوث}} ku ji Aramî hatiye wergirtin ji ber ku bajarrvanên Erebî dibin bo hevkarên xwe ên Aramî-ziman jinfiroş bûbin. ==== Bide ber ==== {{kol3|ku |heres }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Zuhälter|m}} * {{Z|da}}: {{W+|da|alfons}} * {{Z|ar}}: {{W-|ar|قواد|tr=qewwad}} * {{Z|fa}}: {{W-|fa|جاکش|tr=cakeş}}, {{W-|fa|کس‌کش|tr=koskeş}}, {{W+|fa|عوضی}}, {{W+|fa|بی شرف}}, {{W+|fa|قرمساق}}, {{W+|fa|کس کش}} * {{Z|fi}}: {{W+|fi|sutenööri}} * {{Z|fr}}: {{W+|fr|souteneur}} * {{Z|ka}}: {{W-|ka|მამაშა|tr=mamaša}} * {{Z|nl}}: {{W+|nl|pooier}} * {{Z|en}}: {{W+|en|pimp}}, {{W+|en|souteneur}}, {{W+|en|procurer}}, {{W+|en|despicable}}, {{W+|en|unfaithful|guman=erê}}, {{W+|en|ponce|guman=erê}}, {{W+|en|flakey|guman=erê}}, {{W+|en|son of a bitch|guman=erê}}, {{W+|en|undependable|guman=erê}} * {{Z|it}}: {{W+|it|magnaccia}}, {{W+|it|pappone}}, {{W+|it|protettore}} * {{Z|ko}}: {{W-|ko|뚜쟁이|tr=ddujaengi}}, {{W-|ko|뚜|tr=ddu}} * {{Z|hu}}: {{W+|hu|strici}} * {{Z|pl}}: {{W+|pl|alfons}}, {{W+|pl|sutener}} * {{Z|pt}}: {{W-|pt|cafetão}} ''(Brazîlya)'', {{W+|pt|proxeneta|m}}, {{W+|pt|safado|m}}, {{W+|pt|chulo|m}} * {{Z|ro}}: {{W+|ro|proxenet|m}}, {{W+|ro|peşte|m}} * {{Z|ru}}: {{W-|ru|cутенёр|m}}, {{W-|ru|сводник|tr=svódnik}}, {{W-|ru|cводня|tr=svódnja}} * {{Z|sh}}: {{W+|sh|svodnik}} * {{Z|sco}}: {{W-|sco|drùisear|m}} * {{Z|sk}}: {{W-|sk|pasák}} * {{Z|sl}}: {{W+|sl|zvodník}} * {{Z|es}}: {{W+|es|chulo|m}}, {{W+|es|golfo|m}} * {{Z|sw}}: {{W-|sw|buzi}} * {{Z|sv}}: {{W+|sv|hallick}} * {{Z|te}}: {{W-|te|తార్పుడుగాడు|tr=taarpuDugaaDu}} * {{Z|tr}}: {{W+|tr|pezevenk}}, {{W+|tr|teres}} * {{Z|el}}: {{W-|el|σωματέμπορος|tr=somatemporos}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # {{g|ku|teres}} #* {{bêmînak|tr}} # [[qebrax]], [[pêzeweng]], [[qewad]] #* {{bêmînak|tr}} pb3cyloib8fdnneg350ne7m10pe8p9g şeriqîn 0 40248 6347219 6322916 2026-08-30T17:59:35Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347219 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=ngh}} # [[herimîn]], [[qewirîn]], [[verevîn]] #* {{jêder-websîte|ku|jêgirtin=Li rexekî kumsorên ku bi banga melayî ve kurdî ji bo cineta xwe dixin “proje”; li rexa din jî Demîrbaşên ku di şeva cinetê de jî xewa wan '''dişeriqe''' û dixwazin ku mela jî bi kurdî bang bide û li her derî bazara kurdî vebe.|nivîskar=Evdile Koçer|sernav=Bîsîkleta Evdile Demîrbaş û Mercedesên Kurdan|websîte=Diyarname.com|sal=6/2007}} # [[pûç]] bûn, [[xirab]] bûn ==== Tewandin ==== : -şeriq- ==== Bi alfabeyên din ==== * {{ku-ar|شه‌رقین}} ==== Jê ==== {{kol3|ku |şeriqiyayî |şeriqî }} ==== Têkildar ==== {{kol3|ku |şeriqandin }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} p4uwe8vagyz3a8sop8uoje2qfrj48jy rojîn 0 40577 6347227 6346253 2026-08-30T18:19:20Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347227 wikitext text/x-wiki {{bnr-h|Rojîn}} == {{ziman|ku}} == === Etîmolojî === Ji {{qertaf|ku|roj|-în}}. === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{rengdêr|ku}} # [[diyar]], [[eşkere]], [[xwiya]], [[berçav]], [[zelal]], [[geş]] #* {{jêder|ku|jêgirtin=Eger em hûr û kûr dîna xwe bidin şûnewarên wî (Ehmedê Xanî), dê, ji me re '''rojîn''' û eşkere bibe ko mebesta wî li wan şûnewaran tenê vehûnana helbestek evîndariyê, yan çîrokek sade nîne.|[[w:Perwîz Cîhanî|Perwîz Cîhanî]]: ''[[irfan|Irfan]] di Mem û Zîna Ehmedê Xanî de''}} # [[rojane]], [[aktûel]], [[nû]], [[taze]] #* {{bêmînak|ku}} ==== Jê ==== {{kol3|ku |rojînî |rojînîtî |rojîntî }} ==== Bide ber ==== {{kol3|ku |Rojan |Rojen }} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|الشهر|guman=erê}} * {{Z|fa}}: {{W-|fa|پنجره سقفی}}, {{W+|fa|دودکش}} * {{Z|en}}: {{W+|en|fashionable}}, {{W+|en|topical}}, {{W+|en|up-to-date}}, {{W+|en|chp|guman=erê}}, {{W-|en|sky light|guman=erê}}, {{W-|en|smoke hole|guman=erê}}, {{W+|en|chimney cap|guman=erê}} * {{Z|tr}}: {{W+|tr|davlumbaz}}, {{W+|tr|günlük}}, {{W+|tr|ocak}}, {{W+|tr|gündelik}}, {{W+|tr|güncel}}, {{W+|tr|aktüel}}, {{W+|tr|baca|guman=erê}} {{werger-bin}} teb735qcz9cm0z4xvk0pmai23my31z6 qedimandin 0 40755 6347197 6315537 2026-08-30T15:58:20Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347197 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{ku-tewîn-lk|qedimandin|form=gerguhêz|niha=qedimîn|borî=qedimand}} {{lêker|ku|c=x-gh}} # [[pêşkêş]] kirin, [[araste]] kirin, [[raber]] kirin, [[berçav]] kirin, [[diyar]] kirin, [[xuya]] kirin, [[eşkere]] kirin, [[zelal]] kirin, [[rapêş]] kirin, [[nîşan]] dan, [[teqdîm]] kirin, [[daberandin]], [[berpêş]] kirin ==== Tewandin ==== : -qedimîn- ==== Formên alternatîv ==== {{kol3|ku |qedmandin }} ==== Jê ==== {{kol3|ku |qedimandî |qedimîner }} ==== Têkildar ==== {{kol3|ku |qedimîn }} ==== Etîmolojî ==== Têkildarî [[teqdîm]] ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|einführen}}, {{W+|de|vorstellen}}, {{W+|de|reichen}}, {{W+|de|überreichen}}, {{W+|de|anbieten}}, {{W+|de|bieten}}, {{W+|de|aufzeigen}}, {{W+|de|einreichen}}, {{W+|de|offerieren}}, {{W+|de|präsentieren}}, {{W+|de|vorlegen}}, {{W+|de|vorsetzen}}, {{W-|de|Vorlegen|guman=erê}} * {{Z|fi}}: {{W+|fi|esittää}}, {{W+|fi|esitellä}}, {{W+|fi|tarjota}} * {{Z|fr}}: {{W+|fr|présenter}}, {{W+|fr|offrir}}, {{W+|fr|adresser}}, {{W+|fr|dédicacer}}, {{W+|fr|dédier}}, {{W+|fr|représenter}} * {{Z|en}}: to {{W+|en|offer}}, to {{W+|en|put forward}}, {{W+|en|hold forth}}, {{W+|en|serve up}}, {{W+|en|introduce}}, {{W+|en|represent}}, {{W+|en|bring in}}, {{W+|en|confer}}, {{W+|en|emcee}}, {{W+|en|exhibit}}, {{W+|en|initiate}}, {{W+|en|lay}}, {{W+|en|lodge}}, {{W+|en|present}}, {{W+|en|proffer}}, {{W+|en|render}} * {{Z|tr}}: {{W+|tr|sunmak}}, {{W+|tr|yollamak}}, {{W+|tr|göndermek}}, {{W+|tr|takdim etmek}}, {{W+|tr|göstermek}}, {{W+|tr|arz etmek}}, {{W+|tr|sunma}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{jêder-websîte|ku|jêgirtin=Ne bi tenê wêneyên Fewzî Bîlge’yî, wêneyên wênesazên din jî, wê weke civaka kurd em ber bi xwe de '''neqedimandina''' û nenihêrandina; yek, ji ber ku em ji koka civakake feodal û misilman dihatin di war û forma wêneyî de hayê me ji bayê felekê tune bû û em ji hunera wêneyî hatibûn xesandin; dudu, ji ber ku em civakeke bindest bûn û gava ku em çav li xwe, çav li wêneyên xwe diketin ziravê me ji me diqetiya û mahdê me ji me dixeliya.|nivîskar=Rênas Jiyan|sernav=Wêne, [[awêne|a-wêne]]|websîte=Azadiyawelat.com|sal=7/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} 9j0i8ypcam4f8pplx4uts6rrf632hwl çaroke 0 40968 6347178 6346989 2026-08-30T13:45:38Z Wikihez 7344 /* Werger */ sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347178 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[caw|Cawê]] [[tenik]]ê yê [[doşek]] û [[lihêf]] pê [[niximandin]]. #: {{hevmane|ku|rûnivîn|rû|rûlihêf|hêram|hîzar|fote|fûtik|belekî|spîçal|çarçef|fotik}} #* {{bênimûne|ku}} # [[çît|Çîtê]] mirov [[pirç]]a anku [[por]]ê xwe [[niximandin|diniximînin]] (bi taybetî [[jin]]). #: {{hevmane|ku|serpoşk|kevînk|laçik|kefî|egale|dersok|xafik}} #* {{jêder|ku|Cigerxwîn: ''Dengê Pêrîşanê''|jêgirtin=Roja halanê, roja lêdanê <br>Mêr û gernas î, dotmam bi gorî <p>Lo lo pismamo haya te j' te bî <br>'''Çaroka''' min reş li serê te bî}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Formên alternatîv ==== {{kol3|ku |çarok }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Laken|n}}, {{W+|de|Bettlaken|n}} * {{Z|cs}}: {{W+|cs|prostěradlo|n}} * {{Z|zh}}: {{W-|zh|床单|tr=chuángdān}} * {{Z|da}}: {{W+|da|lagen|n}} * {{Z|fi}}: {{W+|fi|lakana}} * {{Z|fr}}: {{W+|fr|drap|m}} * {{Z|nl}}: {{W+|nl|laken|n}} * {{Z|en}}: (bed) [[sheet]] * {{Z|it}}: {{W+|it|lenzuolo|m}} * {{Z|ja}}: {{W+|ja|敷布}}, {{W-|ja|シーツ|tr=shiitsu: 1}}, {{W+|ja|枚}}, {{W-|ja|シート|tr=shiito}} * {{Z|no}}: {{W+|no|laken}} * {{Z|sl}}: {{W+|sl|rjuha|f}} * {{Z|es}}: {{W+|es|sábana|f}} * {{Z|sv}}: {{W+|sv|lakan}} * {{Z|tr}}: {{W+|tr|çarşaf}} {{werger-bin}} j1728geoc3alycn1zf7w56w0wm3a19z kitle 0 41666 6347220 6310262 2026-08-30T18:00:28Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347220 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[blok]], [[kom]], [[grûp]], [[lîg]], [[girse]], [[fraksiyon]], [[gumlat]] #* {{jêder|ku|jêgirtin=Duh şandeyeke bilind ya '''Kutleya''' Sedir bi serokatiya endamê Kutleya Sedir Beha Erecî serdana Polîtburoya YNK-ê kir û digel kargêrê polîtburoya YNK-ê Mela Bextiyar û hejmarek ji endamên PB ya YNK-ê li baregeha PB civiya.|Pukmedia.com, 7/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê|guherto=hemû}} ==== Jê ==== {{kol3|ku |kutlewî |kutleyî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|fi}}: {{W+|fi|ryhmä}}, {{W+|fi|liitto}} * {{Z|fr}}: {{W+|fr|bloc}} * {{Z|he}}: {{W+|he|גוש}} * {{Z|en}}: {{W+|en|bloc}}, {{W+|en|league}}, {{W+|en|group}} * {{Z|it}}: {{W|it|blocco|m}} * {{Z|sv}}: {{W+|sv|block}} * {{Z|tr}}: {{W+|tr|kitle}}, {{W+|tr|kütle}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[girse]] #* {{bênimûne|tr}} # [[cemawer]] #* {{bênimûne|tr}} # [[telp]], [[lod]], [[gutil]], [[kom]] #* {{bênimûne|tr}} hwhbob0jt85ajh5sgqgkz32sj67apki gazinîn 0 44250 6347183 6307103 2026-08-30T13:50:47Z Wikihez 7344 ne nimûneyeke baş e [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347183 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=ngh}} # [[gazin]] kirin, [[gilî]] kirin, [[itiraz]] kirin, xwe [[nerazî]] kirin, [[nalîn]] #* {{jêder-websîte|ku|jêgirtin={{...}}lê di heman demê de jî digazine{{...}}|nivîskar=Enwer Karahan|sernav=Aysel Tugluk nefretê ji mêran dike|websîte=Nefel.com|sal=8/2007}} ==== Tewandin ==== :-gazin- ==== Bi alfabeyên din ==== * {{ku-ar|گازنین}} ==== Jê ==== {{kol3|ku |gazinî |gazinok }} ==== Etîmolojî ==== Ji {{qertaf|ku|gazin|-în}}. ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W|tr|sızlama}}, {{W|tr|sızlayış}}, {{W|tr|yakınmak}}, {{W|tr|sızlanmak}}, {{W|tr|yakınış|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} 5hx5so7pw0d3ldcbvtye2ygn0cqg51x zahir 0 44396 6347226 6244652 2026-08-30T18:18:18Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347226 wikitext text/x-wiki == {{ziman|ku}} == === Etîmolojî === Ji {{ji|ar|ku|ظاهر|tr=żahir}}, têkilî {{g|ar|ظهور|tr=żuhûr|w=[[zihûr]]}}. === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|zahir}} {{rengdêr|ku}} # [[diyar]], [[xwiya]], [[berçav]], [[bînbar]], [[dîtbar]] #* {{J:Mem û Zîn:1692|jêgirtin='''Zahir''' te eger numaye suxra<br>Batin ew e neqşê xame kubra}} ==== Formên alternatîv ==== {{kol3|ku |zihar }} ==== Dijmane ==== {{kol3|ku |batin }} ==== Jê ==== {{kol3|ku |zahirî |zahirîtî |zahirtî }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W-|de|es scheint}} * {{Z|fa}}: {{W+|fa|ظاهر|guman=erê}} * {{Z|tr}}: {{W-|tr|hiç değilse}}, {{W-|tr|en azından}}, {{W+|tr|zahir}}, {{W+|tr|belli}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=}} # [[xuyang]] ==== Werger ==== {{werger-ser}} {{werger-bin}} == {{ziman|tr}} == === Rengdêr === {{rengdêr|tr}} # [[xuya]], [[numa]], [[xonê]], zahir #* {{bêmînak|tr}} # rûyê derve, [[xuyang]], [[dîmen]] #* {{bêmînak|tr}} # [[bêşik]], [[bêguman]], [[elbete]] #* {{bêmînak|tr}} # [[meğer]], diyar e ku, li gorî ku dixuye #* {{bêmînak|tr}} am73lob0dv8eei8rnhphze22ex6ltm0 zendik 0 45007 6347237 6341692 2026-08-30T18:40:33Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347237 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=n}} # {{e|ku|cilûberg}} [[huçik]], [[parçe]]ya [[cil]]ekê ya ji [[mil]]î ta [[zend]]a [[dest]]î digire # {{e|ku|anatomî}} {{mane?|ku}} #* {{jêder-kitêb|ku|nivîskar=w:Huseyin Bektaş|sernav=w:Anatomiya Bedena Mirovan|sal=2004|weşanxane=Weşanên Deng|jêgirtin='''Zendik''' ji 8 hestîyê piçtik pêktê. Ew hestiyana, bi deziyan bi hev va hatine girêdan.}} ==== Bi alfabeyên din ==== * {{ku-ar|زه‌ندك}} ==== Formên alternatîv ==== {{kol3|ku |zendek }} ==== Etîmolojî ==== Ji {{qertaf|ku|zend|-ik}}. ==== Bide ber ==== {{kol3|ku |zendîq }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Ärmel|m}} * {{Z|da}}: {{W+|da|ærme}} * {{Z|ar}}: {{W-|ar|العضد}}, {{W-|ar|الواهنة|guman=erê}} * {{Z|eo}}: {{W-|eo|maniko}} * {{Z|fa}}: {{W+|fa|آستین|guman=erê}} * {{Z|fo}}: {{W-|fo|erma}} * {{Z|fi}}: {{W+|fi|hiha}} * {{Z|fr}}: {{W+|fr|manche}} * {{Z|fy}}: {{W-|fy|mouwe}} * {{Z|nl}}: {{W+|nl|mouw}} * {{Z|en}}: {{W+|en|sleeve}}, {{W-|en|crank web|guman=erê}}, {{W+|en|maniple|guman=erê}}, {{W+|en|web|guman=erê}} * {{Z|is}}: {{W+|is|ermi}} * {{Z|ca}}: {{W+|ca|mànega}}, {{W-|ca|anemoscopi}} * {{Z|pap}}: {{W-|pap|manga}} * {{Z|pt}}: {{W+|pt|manga}} * {{Z|srn}}: {{W-|srn|anu}}, {{W-|srn|mow}} * {{Z|es}}: {{W+|es|manga}} * {{Z|sv}}: {{W+|sv|ärm}} * {{Z|tr}}: {{W+|tr|kolçak}}, {{W+|tr|bileklik}}, {{W+|tr|kolluk}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[zendîq]] #* {{bêmînak|tr}} pli2oq0hkwsanblo5nrmj74jg9pg51c rahêlan 0 45727 6347174 6346917 2026-08-30T13:43:09Z Wikihez 7344 sererastkirin [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347174 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/rɑːheːˈlɑːn/}} * {{ku-kîte}} === Lêker === {{lêker|ku|c=p-gh}} # li [[pey]] kesekî yan tiştekî [[bezîn]] daku wî [[girtin|bigire]], <br>[[dan dû]] daku [[girtin|bigire]] #: {{nm|ku|Seg '''radihêlin''' pisîkan.}} #: {{nm|ku|Wê '''rahêla''' kurrê xwe daku bigire.}} # [[xwezî]] kirin, [[gazî]] rahêlan, [[xuzî rahêlan]], [[hêvî]] xwestin, [[ji dil]] [[hes kirin]] tiştê ku wî/ê bivê çêbibe #* {{bênimûne|ku}} ==== Tewandin ==== :ra-hêl- ==== Bi alfabeyên din ==== * {{ku-ar|ڕاهێلان}} ==== Jê ==== {{kol3|ku |rahêlayî |xuzî rahêlan }} ==== Etîmolojî ==== Ji {{qf|ku|ra-|hêlan}}, bide ber [[rakirdin]] ([[revîn]], [[bazdan]]) ya soranî. ==== Bide ber ==== {{kol3|ku |rahiştin }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|jagen}} * {{Z|cs}}: {{W+|cs|honit}}, {{W-|cs|pronásledovat}} * {{Z|zh}}: {{zh-ts|追逐|追逐}} (zhuīzhú) * {{Z|da}}: {{W-|da|jagte|guman=erê}} * {{Z|id}}: {{W+|id|mengejar}} * {{Z|ar}}: {{W-|ar|يطارد|tr=yutarid}}, {{W-|ar|مطاردة}} * {{Z|et}}: {{W-|et|taga ajama}} * {{Z|fa}}: {{W-|fa|برجای ماندن}} * {{Z|fi}}: {{W+|fi|ajaa takaa}}, {{W+|fi|jahdata}}, {{W+|fi|seurata}} * {{Z|fr}}: {{W+|fr|poursuivre}}, {{W+|fr|chasser}} * [[guwalî]]: [[bugaman]] * {{Z|nl}}: {{W+|nl|achternazitten}}, {{W-|nl|achternajagen}} * {{Z|he}}: {{W-|he|לרדוף|tr=lirdof}} * {{Z|io}}: {{W+|io|chasar}} * {{Z|en}}: to {{W+|en|chase}}, to {{W+|en|pursue}}, to {{W+|en|hunt}}, to {{W+|en|follow}}, (2) to {{W-|en|wish for}}, {{W+|en|assailing|guman=erê}}, {{W+|en|attacking|guman=erê}}, {{W+|en|go at|guman=erê}}, {{W+|en|go for|guman=erê}} * {{Z|it}}: {{W+|it|cacciare}} * {{Z|is}}: {{W-|is|elta}} * [[jalinguyî]]: [[gundumman]] * {{Z|ja}}: {{W-|ja|追跡する}} * {{Z|ko}}: [[쫓다]] (jjochda, {{W-|ko|jjotda)}} * {{Z|la}}: {{W-|la|captare}} * {{Z|lv}}: [[dzīties pakaļ]]; [[vajāt]] * {{Z|lt}}: {{W+|lt|vytis}}, {{W-|lt|persekioti}} * {{Z|hu}}: {{W+|hu|üldöz}} * {{Z|no}}: {{W+|no|løpe}}, {{W-|no|jage etter}}, {{W+|no|forfølge}} * {{Z|pl}}: {{W+|pl|ścigać}} * {{Z|pt}}: {{W-|pt|perseguir#Portuguese}} * {{Z|ro}}: a [[urmări]] * {{Z|ru}}: {{W+|ru|гнаться}} * {{Z|sk}}: {{W-|sk|prenasledovať}}, {{W-|sk|hnať sa}} * {{Z|sl}}: [[loviti]]; [[zasledovati]] * {{Z|es}}: {{W-|es|perseguir#Spanish}} * {{Z|sv}}: {{W-|sv|jaga#Swedish}}, {{W+|sv|förfölja}} * {{Z|te}}: {{W-|te|వెంటాడు|tr=veMTaaDu}}, {{W-|te|తరుము|tr=tarumu}} * {{Z|tr}}: {{W+|tr|kovalamak}}, {{W+|tr|peşinden koşmak}}, {{W+|tr|kapmak}}, {{W+|tr|sıklaştırmak}} * {{Z|el}}: {{W+|el|κυνηγώ}}, {{W+|el|καταδιώκω}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{jêder|ku|jêgirtin=Duhî şîretkarê taybetî yê rêberê Şoreşa Îslamî ya Îranê general Yehya Rehîm Sefewî di axiftineka xwe de ligel PARS-TV diyar kir ko Îran wan deveran top baran dike û ew dê ji bo '''rahêlan''' û lêxistina PJAK-ê li ser wî karê xwe berdewam bibin.|Nefel.com, 9/2007}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} 0cnyg1o5fa88bvcs22rzuyr0dw03d28 şemamok 0 45853 6347182 6322838 2026-08-30T13:48:13Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347182 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:Şemamok.jpg|thumb|'''Şemamok'''ek]] {{navdêr|ku|z=m}} # Hin [[cûn]] [[gundor]]ên [[hûrik]] in. #* {{jêder|ku|jêgirtin=Sê hawe te deng, yek ji sira bayê siba ye<br>Hawayê dî ji dengê xuşîna dehl û reza ye<br><br>Hawê sisîya ji bihna '''şemamok''' û gula ye<br>Lewra ku li dinyê tu bi nav û tu meşûr e.|''Bilbilê Dilşadî'', [[w:Seydayê Tîrêj|Seydayê Tîrêj]]}} # {{f|ku|argo}} [[memik|Memik]], [[çiçik]], [[bersîng]]ên [[jin]]an. #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|شه‌مامۆك}} ==== Formên alternatîv ==== {{kol3|ku |şimamok }} ==== Jê ==== {{kol3|ku |Şemam }} ==== Etîmolojî ==== Ji {{qertaf|ku|شَمَّام‎|w1=[[şemam]], [[gundor]]|ziman1=ar|-ok}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W-|de|Warzenmelone}}, {{W+|de|Frauenbrüste}} * {{Z|ar}}: {{W-|ar|شَمَّام‎}} * {{Z|en}}: {{W-|en|micro melon}}, {{W-|en|rich sweetness 132 melon}}, {{W+|en|cantaloupe|guman=erê}}, {{W+|en|musk melon|guman=erê}}, {{W-|en|sweet melon|guman=erê}} * {{Z|tr}}: {{W+|tr|şamama}}, {{W+|tr|şamama gibi}} {{werger-bin}} {{mijar|ku|riwek}} 3pife2ke6rgxouad4lgk70ifjtibwio seksiyon 0 46252 6347184 6317242 2026-08-30T13:53:17Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347184 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[ker]], [[pişk]], [[beş]], [[par]], [[pirt]], [[kert]], [[ta]], [[hêl]], [[rex]], [[çeq]], [[liq]], [[sektor]], [[sektor]], [[branş]] #* {{jêder-websîte|ku|jêgirtin=Ew [Keremê Anqosî] herwiha tevî çend kongre û konfêransên navnetewî yên zanyarî bûye, ko derheqa problêmên rohilatzanîyê, kurdzanîyê û dînê êzdîyan da bûne. Sala 1992an bingehê rêxistina bi navê “Civaka hemwelatîyên kurd yên Gurcistanê“ danî. Sala 1995an 5 rêxistinên kurdan yên civakî ketine nava wê rêxistinê. Paşê, sala 1998an bi înîsîatîva wî ew hate binavkirinê wek “Yekîtîya êzdîyên Gurcistanê“. Demekê ewî serokatî li wê rêxistinê kir, lê paşê yek ji wan kesan bû, ko bû bingehdarê rêxistina “Fonda navnetewî ya parastina maf û mîrata dînî ya gelê kurd“, “Navbenda dînê Êzdîyan“, “Yekîtîya ronakbîrên kurdên Gurcistanê“, “Fonda '''sêksyona''' kurdî ya UNESCOyê li Gurcistanê“ saz kir. Îro jî, ko emirê wî zêdeyî 70 salan e, dersên zimanê kurdî dide zarokan, berpirsyarîya malpera www.kurd.ge dike.|nivîskar=[[w:Têmûrê Xelîl|Têmûrê Xelîl]]|sernav=Kurdên Ermenistanê yên Gurcistanê li ber çavan winda kirin|websîte=Nefel.com|sal=5/2011}} # [[bend]], [[made]], [[paragraf]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== Bi rêya {{ji|fr|ku|section}}, ji {{ji|la|ku|sectio}} ji [[secare]] ([[ker]] kirin, [[birîn]]) ==== Werger ==== {{werger-ser}} * {{Z|af}}: {{W+|af|afdeling}} * {{Z|de}}: {{W+|de|Sektion|f}} * {{Z|cs}}: {{W+|cs|sekce|f}} * {{Z|da}}: {{W+|da|afdeling}} * {{Z|eo}}: {{W+|eo|sekcio}} * {{Z|fo}}: {{W-|fo|deild}} * {{Z|fr}}: {{W+|fr|section}} * {{Z|fy}}: {{W-|fy|ôfdieling}} * {{Z|nl}}: {{W+|nl|afdeling}}, {{W+|nl|geleding}}, {{W+|nl|sectie}} * {{Z|he}}: {{W+|he|בתר|cuda=בֶּתֶר}} * {{Z|en}}: {{W+|en|section}}, {{W+|en|branch}}, {{W+|en|chapter}} * {{Z|it}}: {{W+|it|divisione}} * {{Z|ca}}: {{W+|ca|secció}} * {{Z|ms}}: {{W+|ms|bagian}} * {{Z|pt}}: {{W+|pt|seção}} * {{Z|es}}: {{W+|es|departamento}}, {{W+|es|sección}}, {{W-|es|subdivisión}} * {{Z|sv}}: {{W+|sv|sektion}} * {{Z|tr}}: {{W+|tr|branş}}, {{W+|tr|seksiyon}}, {{W+|tr|bölüm}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[beş]], [[liq]], [[hob]], [[seksiyon]] #* {{bêmînak|tr}} 5nht3xkvnop64leqdtcffgsrxauxnt0 manewî 0 46996 6347217 6329650 2026-08-30T17:55:18Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347217 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{rengdêr|ku}} # Ne [[madî]] yan [[bedenî]]. #: {{hevmane|ku|arişî|ruhî|canî|giyanî|exlaqî|moralî|psîkolojî|sincî}} #: {{nm|ku|alîkariya madî û '''manewî'''|hem pare û hem jî sempatî|rêz=1}} #: {{nm|ku|zarokên '''manewî'''|zarokên ku ne yên kesekî bi xwe ne lê wî xwedî kirine|rêz=1}} #: {{nm|ku|Gelek kes Mistefa Barzanî wek bavê '''manewî''' yê neteweya kurd dipejirînin.}} #* {{jêder-websîte|ku|jêgirtin=Piştî ku nexweşiya wî ket rojevê, navê wî li pir deran hat lêkirin. Bi taybetî jî Şaredariya Amedê ji aliyê madî û '''manewî''' ve pir xizmet girtin ser xwe. Hem belediye bi xwe seferber bû hem jî ew şevbêrkên dengbêjan ên ku ji bo xatirê wî hatibûn amade kirin gelek watedar bûn.|nivîskar=Aydin Dere|sernav=Pişti Mehmed Uzun rexneyên vekirî|websîte=Amidakurd.com|sal=11/2007}} ==== Formên alternatîv ==== {{kol3|ku |mahnewî |mehnewî |me'newî }} ==== Jê ==== {{kol3|ku |manewîtî |manewiyat |manewiyet }} ==== Etîmolojî ==== Ji {{ji|ar|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|geistig}} * {{Z|fa}}: {{W+|fa|معنوی}} * {{Z|fi}}: {{W+|fi|henkinen}} * {{Z|en}}: {{W+|en|spiritual}}, {{W+|en|intangible}}, {{W+|en|immaterial}}, {{W+|en|moral}}, {{W+|en|pastoral}}, {{W+|en|psychological}}, {{W+|en|unworldly}}, {{W|en|manichean|guman=erê}} * {{Z|tr}}: {{W+|tr|manevi}}, {{W+|tr|tinsel}} {{werger-bin}} 06twgz24rnc9kh52tnnhd4jkknk62me tatêl 0 47515 6347230 6318453 2026-08-30T18:27:05Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347230 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[mereq|Mereq]], [[xemxwerî]], [[balkêşî]], [[çavzêlkî]], [[etir]]. #* {{jêder|ku|jêgirtin=Mirîşka me hêkên nû dike, ketiye '''tatêla''' dewleta tirk, ya perçe bibe. Ya kurd bibin xwedî dewlet? Di şûna xwediyê xwe de, dilerizî lê feydeya tirsê ji ecelê re tuneye.|xwendevanek bi navê Firat di Netkurd.com de, 12/2007}} # {{kontrol|rêz=erê|[[hewes]]}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |tatol }} ==== Jê ==== {{kol3|ku|cure=Jê |tatêl kirin<crz:lêker> |tatêlkirin<crz:navdêr> |tatêlkirî<crz:rengdêr> }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== {{kol3|ku |tatîl }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Neugier|f}}, {{W+|de|Neugierde|f}} * {{Z|az}}: {{W+|az|maraq|xs=Azeri}} * {{Z|cs}}: {{W-|cs|zvědavost|f}} * {{Z|zh}}: {{W-|zh|好奇|tr=haoqi}}, {{W-|zh|好奇心|tr=haoqixin}}, {{W-|zh|珍品|tr=zhenpin}} * {{Z|fa}}: {{W+|fa|کنجکاوی}} * {{Z|fi}}: {{W+|fi|uteliaisuus}} * {{Z|fr}}: {{W+|fr|curiosité}} * {{Z|nl}}: {{W+|nl|nieuwsgierigheid}} * {{Z|he}}: {{W-|he|סקרנות|tr=saqranut}} * {{Z|ang}}: {{W-|ang|fyrwet|n}} * {{Z|it}}: {{W+|it|curiosità}} * {{Z|ja}}: {{W-|ja|好奇心|tr=こうきしん kōkishin}}, {{W-|ja|珍奇|tr=ちんき chinki}} * {{Z|ko}}: {{W+|ko|호기심}} * {{Z|la}}: [[curiositas]] ''nominative'', curiositatis ''genitive'' * {{Z|lt}}: {{W-|lt|smalsumas|m}}, {{W-|lt|žingeidumas|m}} * {{Z|mk}}: {{W-|mk|љубопитност|f}} * {{Z|pt}}: {{W+|pt|curiosidade}} * {{Z|ru}}: {{W+|ru|любопытство|tr=lyubopytstvo}} * {{Z|sl}}: {{W+|sl|radovednost|f}} * {{Z|es}}: {{W+|es|curiosidad}} * {{Z|sv}}: {{W+|sv|nyfikenhet}} * {{Z|tr}}: {{W+|tr|merak}} * {{Z|el}}: {{W+|el|περιέργεια|tr=periérgeia}} {{werger-bin}} eshpe6sbtq1x6rsuv72n84ju9fd20jc mikemel 0 47753 6347242 6346257 2026-08-30T18:44:39Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347242 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|mikemel}} {{rengdêr|ku}} # [[tekûz]], [[kamil]], [[temam]], [[bêkêmasî]], [[bêqisûr]], [[bê-êb]], [[bêeyb]] #* {{jêder-websîte|ku|jêgirtin=Kurdên li metropolan bi rojan rûbirûyî êrîş û gefxwarinên girseyên nijadperest hatin hiştin. Li cîhên wek Îstenbol, Îzmîr, Bûrsa, Aydin, Îzmîr, Bûrsa, Aydinê tax û xanîyên ko Kurd lê dijîyan heta bi nîvê şevê hatin dorpêçkirin, otobusên ko ji bajarên Kurdistanê dihatin, hatin rawestandin, rêwî bi zorê hatin peyakirin û bi darê zorê ‘îstîklal marşi’ (sirûda netewî ya Tirkan) bi wan dan xwendin; atmosfera teroreke giştî pêk anîn. Dûre, serokê Partîya Hêzên Çekdar ên Tirk bi daxuyanîyekê dîyar kir ko ew van çalakîyan '''mukemel''' dibîne û bi awayekî bi kontrol şûnve vekişîyan.|nivîskar=Fuat Onen|sernav=Welatek di [[ronahî|ronkaya]] rojê de ji gelên wî yên otokton hat dizîn|websîte=Nefel.com|sal=12/2007}} # [[pirr]] [[baş]], gelek [[hêja]] ==== Formên alternatîv ==== {{kol3|ku |mikemmel |mukemel |mekemmel }} ==== Jê ==== {{kol3|ku |mikemelane |mikemelen |mikemelî |mikemelîtî |mikemeltî }} ==== Têkildar ==== {{col3|ku |kamil |kemal |keml |kemilandin |kemilîn }} ==== Etîmolojî ==== Ji {{deyn|ar|ku}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|ausgezeichnet}}, {{W+|de|einwandfrei}}, {{W+|de|großartig}}, {{W+|de|prima}}, {{W+|de|vorzüglich}}, {{W+|de|wunderbar}}, {{W|de|vortrefflich}}, {{W|de|trefflich|guman=erê}}, {{W|de|Ideal|guman=erê}} * {{Z|fi}}: {{W+|fi|täydellinen}}, {{W+|fi|virheetön}}, {{W+|fi|erinomainen}}, {{W+|fi|mainio}} * {{Z|fr}}: {{W+|fr|parfait}} * {{Z|en}}: {{W+|en|perfect}}, {{W+|en|complete}}, {{W+|en|excellent}}, {{W+|en|brilliant}}, {{W+|en|fabulous}}, {{W+|en|faultless}}, {{W+|en|flawless}}, {{W+|en|glittering}}, {{W+|en|grand}}, {{W+|en|ideal}}, {{W+|en|immaculate}}, {{W+|en|impeccable}}, {{W+|en|masterly}}, {{W+|en|prodigious}}, {{W+|en|smashing}}, {{W+|en|spectacular}}, {{W+|en|splendid}}, {{W+|en|superb}}, {{W+|en|terrific}}, {{W+|en|ultimate}}, {{W+|en|dandy}}, {{W+|en|fabulously}} * {{Z|tr}}: {{W+|tr|mükemmel}}, {{W+|tr|eksiksiz}}, {{W+|tr|kusursuz}}, {{W+|tr|tam}}, {{W+|tr|yetkin}}, {{W+|tr|şahane}}, {{W+|tr|tamam}}, {{W+|tr|olgun}}, {{W+|tr|noksansız}}, {{W+|tr|mükemel}}, {{W+|tr|harika}}, {{W|tr|ilâhî|guman=erê}}, {{W|tr|komple|guman=erê}} {{werger-bin}} tin8524pvs35y12xdaj0xxgysfzes2c ready 0 47866 6347256 6343850 2026-08-30T20:20:21Z ~2026-45593-87 15272 /* Hoker */ 6347256 wikitext text/x-wiki == {{ziman|en}} == === Bilêvkirin === :{{ku-tîp|rîdî}} * {{deng|en|en-us-ready.ogg|dever=DYA}} * {{deng|en|En-uk-ready.ogg|dever=QY}} * {{deng|en|LL-Q1860 (eng)-Back ache-ready.wav|Deng|dever=London,QY}} * {{deng|en|LL-Q1860 (eng)-Nattes à chat-ready.wav|Deng|dever=}} * {{deng|en|LL-Q1860 (eng)-Wodencafe-ready.wav|Deng|dever=Teksas, DYA}} === Hoker === {{hoker|en}} # [[amade]], [[hazir]], gîf, têz, saz, berhev, gellale, rraz #* {{bêmînak|en}} 8gjvx8xooowuwl61l3xi0uhfu2exq32 alarm 0 48474 6347195 6296440 2026-08-30T15:56:02Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347195 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{navdêr|ku|z=m}} # [[hişdarî]], [[agadarî]], [[hişyar]]kirin, [[agadar]]kirin, [[îmdad]], [[îkaz]] #* {{jêder|ku|jêgirtin=Dîsa du deqîqe beriya sieta xwe heşyar bûbû. Bi salan e ku her şev beriya razanê '''alarma''' sieta xwe li ser şeş û nîvan eyar dikir. Di destpêkê de piştî çend hefteyan bi '''alarma''' sieta xwe heşyar bûbû. Lê demeke dûr e ku du-sê deqîqe beriya '''alarmê''' heşyar dibe. Ji bona vê rewşê digot, "sieta giyana min û sieta li ber serê min li hevûdu dinihêrin, bi hevûdu re durust in."|Jan Geşo: ''Girtiyê gardiyanê nav dilê xwe ye'', Dema Nû, hj. 77, 2003}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== Bi rêya {{ji|fr|ku|alarme}} yan {{ji|en|ku|alarm}} ji {{ji|it|ku|allarme|t=dest biavêjin çekan / sîlehan}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Alarm|n}}, {{W+|de|Alarmbereitschaft|n}} * {{Z|id}}: {{W+|id|alarm}} * {{Z|fa}}: {{W+|fa|هشدار}} * {{Z|fi}}: {{W+|fi|hälytys}} * {{Z|fr}}: {{W+|fr|alarme}} * {{Z|io}}: {{W+|io|alarmo}} * {{Z|en}}: {{W+|en|alarm}} * {{Z|pt}}: {{W+|pt|alarme|n}} * {{Z|es}}: {{W+|es|alarma}} * {{Z|tr}}: {{W+|tr|alarm}}, {{W+|tr|alârm}} {{werger-bin}} == {{ziman|en}} == === Bilêvkirin === * {{deng|en|en-us-alarm.ogg|dever=DYA}} * {{deng|en|LL-Q1860 (eng)-Wodencafe-alarm.wav|Deng|dever=Teksas, DYA}} * {{deng|en|LL-Q1860 (eng)-Grendelkhan-alarm.wav|Deng|dever=Connecticut, DYA}} === Navdêr === {{navdêr|en}} # [[zeng]], [[deng]]ê [[borî|boriyê]], dengê [[borazan]]ê #* {{bêmînak|en}} === Lêker === {{en-lêker}} # [[agehdar kirin]], [[hişyar kirin]] <ref>Ferhenga Kurdî-Îngîlîzî ya Salah Sadallah</ref> #* {{bêmînak|en}} === Çavkanî === {{çavkanî}} k97t32we9wndh6jk2njwspg9ys5rhiy masturbasyon 0 48868 6347231 6311696 2026-08-30T18:27:59Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347231 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[rep|Rep]]kirina [[kîr]]ê xwe yan [[xurrandin]]a [[quz]]ê xwe. #: {{hevmane|ku|destperkî|destper|destperk|destperrî|lêdan|îstîmna|onanîzm}} #* {{jêder|ku|jêgirtin=Mamosteyê min alîkarîya min bike. Ez jineka 29 sal î û zewicî me. Min roja berê li malê bi serê xwe '''masturbasyon''' kir. Paşê min dît ku gustîlka min ne di pêçîka min de ye, êvarê jî sanco dest pê kir. Mêrê min dixwazê û ez jê direvim, ez ê niha çi bikim?|Netkurd.com, 2/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== Bi rêya {{ji|fr|ku|masturbation}}, ji {{ji|la|ku|masturbārī}} belkî ji [[manus]] (dest) + [[turbāre]] ([[têk vedan]]) anku bi destan têk vedan ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Selbstbefriedigung|f}}, {{W|de|Masturbation|f}}, {{W+|de|onanie}}, {{W+|de|handbetrieb}}, {{W|de|Onanie|f}} * {{Z|fa}}: {{W+|fa|استمنا|guman=erê}} * {{Z|fi}}: {{W+|fi|masturbaatio}}, {{W+|fi|itsetyydytys}}, {{W+|fi|onania}} * {{Z|fr}}: {{W+|fr|masturbation}}, {{W+|fr|onanisme}} * {{Z|en}}: {{W+|en|masturbation}}, (crude) {{W+|en|wanking}} * {{Z|it}}: {{W+|it|masturbazione}} * {{Z|ru}}: {{W+|ru|онанизм}}, {{W+|ru|мастурбация}} * {{Z|es}}: {{W+|es|masturbación}}, {{W+|es|onanismo}} * {{Z|sv}}: {{W+|sv|självtillfredsställelse}}, {{W+|sv|onani}}, {{W+|sv|masturbation}} * {{Z|tr}}: {{W+|tr|mastürbasyon}}, {{W+|tr|onanizm}}, {{W+|tr|istimna}} {{werger-bin}} 8zuncee9mnwq36h9mu6kbcff979qyrx 6347253 6347231 2026-08-30T20:12:12Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347253 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[rep|Repkirina]] [[kîr]]ê xwe yan [[xurrandin]]a [[quz]]ê xwe. #: {{hevmane|ku|destperkî|destper|destperk|destperrî|lêdan|îstîmna|onanîzm}} #* {{jêder|ku|jêgirtin=Mamosteyê min alîkarîya min bike. Ez jineka 29 sal î û zewicî me. Min roja berê li malê bi serê xwe '''masturbasyon''' kir. Paşê min dît ku gustîlka min ne di pêçîka min de ye, êvarê jî sanco dest pê kir. Mêrê min dixwazê û ez jê direvim, ez ê niha çi bikim?|Netkurd.com, 2/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== Bi rêya {{ji|fr|ku|masturbation}}, ji {{ji|la|ku|masturbārī}} belkî ji [[manus]] (dest) + [[turbāre]] ([[têk vedan]]) anku bi destan têk vedan ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Selbstbefriedigung|f}}, {{W|de|Masturbation|f}}, {{W+|de|onanie}}, {{W+|de|handbetrieb}}, {{W|de|Onanie|f}} * {{Z|fa}}: {{W+|fa|استمنا|guman=erê}} * {{Z|fi}}: {{W+|fi|masturbaatio}}, {{W+|fi|itsetyydytys}}, {{W+|fi|onania}} * {{Z|fr}}: {{W+|fr|masturbation}}, {{W+|fr|onanisme}} * {{Z|en}}: {{W+|en|masturbation}}, (crude) {{W+|en|wanking}} * {{Z|it}}: {{W+|it|masturbazione}} * {{Z|ru}}: {{W+|ru|онанизм}}, {{W+|ru|мастурбация}} * {{Z|es}}: {{W+|es|masturbación}}, {{W+|es|onanismo}} * {{Z|sv}}: {{W+|sv|självtillfredsställelse}}, {{W+|sv|onani}}, {{W+|sv|masturbation}} * {{Z|tr}}: {{W+|tr|mastürbasyon}}, {{W+|tr|onanizm}}, {{W+|tr|istimna}} {{werger-bin}} kqrnnc79o1p6hlefycxkrz26540z1oq tetbîq 0 49039 6347232 6318987 2026-08-30T18:30:32Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347232 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[bi kar anîn|bikaranîn]], [[di kar birin]], [[karbird]], [[sepandin]], [[peyikandin]], [[xebitandin]], [[pratîzekirin]] #* {{jêder|ku|jêgirtin=Li Tirkiyeyê demokratîkbûn pirseka girîng e. Beşdarîya bo Yekîtîya Ewropayê û pêkanîna demokratîkbûnê, amanceka bingehîn a hukûmetan e. Wekî mînak, hukûmeta Partîya Edalet û Pêşveçûnê (AKP) carînan behsa vê amancê dike. Demokratîkbûn jî, ji rûyê polîtîkaya kurd ya antî-demokratîk çênabe. Ji ber vê yekê, di warê beşdarîya bo Yekîtîya Ewropayê de pêşveçûneka ciddî pêk nayê. Di pirsa kurd û Kurdistanê de, polîtîkaya pingehîn ya tirk asîmîlasyon e. Ji dema Îttîhad we Teraqqîyê û bi vir de bona pêkanîna asîmîlasyonanê her şêwe metod têne '''tetbîqkirin'''. Tetbîqatên asîmîlasyonê ku ji salên dawîn yên dewleta Osmanî, ango ji dema Îttîhad we Teraqqîyê dest pêkiribûn, bi destpêkirina dema komara Tirkiyeyê re hîn bêhtir bi awayekî sîstematîk û biryardar hatin kirin. Asîmîlekirina kurdan bo tirkîtîyê û asîmîlekirina elewîyan bo muslamntîyê, polîtîkayeka bingehîn ya dewletê ye. Tunekirina ew kurdê ku bo tirkîtîyê nehatiye asîmîlekirin, dîsa, polîtîkayeka bingehîn ya dewletê ye.|İsmail Beşikçi: ''Komeleya Piştgiriya Jiyana Nûjen Çi Dide Kurdan?'', wergerrandin: Roşan Lezgîn, Peyamaazadi.com, 3/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |tatbîq }} ==== Jê ==== {{kol3|ku |tetbîq kirin<crz:lêker> |tetbîqkirin<crz:navdêr> |tetbîqkirî<crz:rengdêr> |tetbîqat |tetbîqî |tetbîqker }} ==== Etîmolojî ==== Ji {{ji|ar|ku|تَطْبِيق‎}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Praxis|f}} * {{Z|en}}: {{W+|en|application}}, {{W+|en|exercise}}, {{W+|en|practice}}, [[put]]ting sth into [[effect]] * {{Z|tr}}: {{W+|tr|uygulama}}, {{W+|tr|yakıştırma}}, [[yer]]ine [[getirme]], {{W-|tr|Karşılaştırma}}, {{W+|tr|tatbik}} {{werger-bin}} hbhq3psocwt4e3n5undqvcs1qwoblp0 serbor 0 49913 6347188 6317399 2026-08-30T14:01:49Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347188 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pir|Pir]]a ku di ser [[rê]]yekê re [[derbas]] dibe; [[rê]]ya ku di ser [[rê]]yeke din re [[borîn|dibore]]. #: {{hevmane|ku|jorbor}} #* {{jêder|ku|jêgirtin=Şaredariya Bajarê Mezin a Diyarbekirê, ji bo hişmendiya bajarîbûnê pêşve bibe û bajareke paqij ava bike li '''serbuhuran''' (Ustgeçit) nivîsên hişyariyê bi karîkatorên bi şiîr, daliqandin.|Netkurd.com, 5/2008}} # [[hebûn|Hebûn]]a [[ezmon]]ê; bi [[ser]]î [[hatin]] bi[[reng]]ekê ko [[miva]] jê [[hat]]iye [[wergirtin]]. #: {{hevmane|ku|}} #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|سه‌ربۆر}} ==== Formên alternatîv ==== {{kol3|ku |serbur |serbihor |serbuhor |serbuhur }} ==== Dijmane ==== {{kol3|ku |binbor |jêrbor }} ==== Etîmolojî ==== Ji {{qertaf|ku|ser-|bor}}. ==== Bide ber ==== {{kol3|ku |serborî }} ==== Pend ==== * ([[gût]]ê [[pîrê]] te [[bor]] yan [[serbor]], [[gût]]ê min [[serbor]]) ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|جسر}}, {{W-|ar|التجربة}}, {{W-|ar|الحنكة|guman=erê}}, {{W-|ar|الآیة|guman=erê}} * {{Z|fi}}: {{W+|fi|ylikulkusilta}} * {{Z|en}}: {{W+|en|bridge}}, {{W+|en|overpass}}, {{W+|en|experience}} * {{Z|tr}}: {{W+|tr|üst geçit}} {{werger-bin}} 49f748tc95ravs1w94lymid2pgu32l8 6347189 6347188 2026-08-30T14:02:04Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347189 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pir|Pir]]a ku di ser [[rê]]yekê re [[derbas]] dibe; [[rê]]ya ku di ser [[rê]]yeke din re [[borîn|dibore]]. #: {{hevmane|ku|jorbor}} #* {{jêder|ku|jêgirtin=Şaredariya Bajarê Mezin a Diyarbekirê, ji bo hişmendiya bajarîbûnê pêşve bibe û bajareke paqij ava bike li '''serbuhuran''' (Ustgeçit) nivîsên hişyariyê bi karîkatorên bi şiîr, daliqandin.|Netkurd.com, 5/2008}} # [[hebûn|Hebûn]]a [[ezmon]]ê; bi [[ser]]î [[hatin]] bi[[reng]]ekê ko [[miva]] jê [[hat]]iye [[wergirtin]]. #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|سه‌ربۆر}} ==== Formên alternatîv ==== {{kol3|ku |serbur |serbihor |serbuhor |serbuhur }} ==== Dijmane ==== {{kol3|ku |binbor |jêrbor }} ==== Etîmolojî ==== Ji {{qertaf|ku|ser-|bor}}. ==== Bide ber ==== {{kol3|ku |serborî }} ==== Pend ==== * ([[gût]]ê [[pîrê]] te [[bor]] yan [[serbor]], [[gût]]ê min [[serbor]]) ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|جسر}}, {{W-|ar|التجربة}}, {{W-|ar|الحنكة|guman=erê}}, {{W-|ar|الآیة|guman=erê}} * {{Z|fi}}: {{W+|fi|ylikulkusilta}} * {{Z|en}}: {{W+|en|bridge}}, {{W+|en|overpass}}, {{W+|en|experience}} * {{Z|tr}}: {{W+|tr|üst geçit}} {{werger-bin}} 02j26ditl5933obqyaqpmhtuwr5keye 6347190 6347189 2026-08-30T15:12:11Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347190 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[pir|Pira]] ku di ser [[rê]]yekê re [[derbas]] dibe; [[rê]]ya ku di ser [[rê]]yeke din re [[borîn|dibore]]. #: {{hevmane|ku|jorbor}} #* {{jêder|ku|jêgirtin=Şaredariya Bajarê Mezin a Diyarbekirê, ji bo hişmendiya bajarîbûnê pêşve bibe û bajareke paqij ava bike li '''serbuhuran''' (Ustgeçit) nivîsên hişyariyê bi karîkatorên bi şiîr, daliqandin.|Netkurd.com, 5/2008}} # [[hebûn|Hebûna]] [[ezmon]]ê; bi [[ser]]î [[hatin]] bi[[reng]]ekê ko [[miva]] jê [[hat]]iye [[wergirtin]]. #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|سه‌ربۆر}} ==== Formên alternatîv ==== {{kol3|ku |serbur |serbihor |serbuhor |serbuhur }} ==== Dijmane ==== {{kol3|ku |binbor |jêrbor }} ==== Etîmolojî ==== Ji {{qertaf|ku|ser-|bor}}. ==== Bide ber ==== {{kol3|ku |serborî }} ==== Pend ==== * ([[gût]]ê [[pîrê]] te [[bor]] yan [[serbor]], [[gût]]ê min [[serbor]]) ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|جسر}}, {{W-|ar|التجربة}}, {{W-|ar|الحنكة|guman=erê}}, {{W-|ar|الآیة|guman=erê}} * {{Z|fi}}: {{W+|fi|ylikulkusilta}} * {{Z|en}}: {{W+|en|bridge}}, {{W+|en|overpass}}, {{W+|en|experience}} * {{Z|tr}}: {{W+|tr|üst geçit}} {{werger-bin}} 1ocrrmhk32eyhjf3ip08iok886q0xsp nazenîn 0 50200 6347176 6346971 2026-08-30T13:45:17Z Wikihez 7344 /* Werger */ sererastkirin [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347176 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Rengdêr === {{ku-tewîn-rd|nazenîn}} {{rengdêr|ku}} # [[nazdar]] #* {{bêmînak|ku}} # [[bejnzirav]], [[narîn]], [[zirav]] û [[delal]] #* {{jêder|ku|jêgirtin=Gulên roja pêşîn xamekên Flanderê<br>şirîniya hîlebaziyê ya mirin rûyê xwe pê reng dide<br>û hûn sorgulên '''nazenîn''' kulîlkên şopa vekişînê<br>rengê agirê dûr sorgulên Anjou.|Louis Aragon: ''Sorgul û Xamekgul'', wergerandin: Husein Muhammed, Kovara MEHNAME, jêgirtin: 7/2008}} ==== Bi alfabeyên din==== * {{ku-ar|نازه‌نین}} ==== Jê ==== {{kol3|ku |nazenînî |nazenînîtî |nazenîntî }} ==== Etîmolojî ==== Ji {{ji|ira}}, soranî {{g|ckb|نازه‌نین|tr=nazenîn}}, farisî {{g|fa|نازنین|tr=nazenîn}}, têkilî ''[[naz]]'', ''[[nazdar]]'', ''[[nazik]]''. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|angenehm}}, {{W+|de|lieblich}}, {{W+|de|tüttelig}}, {{W+|de|schlank}} * {{Z|cs}}: {{W|cs|štíhlý|m}}, {{W|cs|útlý|m}} * {{Z|zh}}: {{W+|zh|苗條}}, {{W-|zh|苗条|tr=miáotiáo}} * {{Z|ar}}: {{W|ar|نحيف}} {{IPAchar|(naħíf)}} * {{Z|fa}}: {{W+|fa|خوشمزه}}, {{W+|fa|لطیف}}, {{W+|fa|نغز}} * {{Z|fi}}: {{W+|fi|hoikka}} * {{Z|fr}}: {{W+|fr|svelte}}, {{W+|fr|mince}} * {{Z|nl}}: {{W+|nl|slank}} * {{Z|en}}: {{W+|en|slender}}, {{W+|en|slim}}, {{W+|en|lean}}, {{W+|en|lithe}}, {{W+|en|svelte}}, [[willowy]]<br> (thin in an attractive way), {{W+|en|dandy}}, {{W+|en|distingue}}, {{W+|en|refined}}, {{W+|en|dainty}}, {{W+|en|nice|guman=erê}}, {{W|en|graceful|guman=erê}}, {{W|en|sissy|guman=erê}} * {{Z|it}}: {{W+|it|snello}} * {{Z|ja}}: {{W-|ja|ほっそりした|tr=hossori shita}} * {{Z|ko}}: {{W-|ko|날씬한|tr=nalssinhan}} * {{Z|hu}}: {{W+|hu|sovány}} * {{Z|pt}}: {{W+|pt|esbelto}}, {{W+|pt|magro}} * {{Z|ru}}: {{W-|ru|тонкий|tr=tónkij}} * {{Z|es}}: {{W+|es|esbelto}} * {{Z|sv}}: {{W+|sv|slank}} * [[teterî]]: [[cuka]] * {{Z|tr}}: {{W+|tr|nazenin}}, {{W+|tr|nazdar}}, {{W+|tr|narin}}, {{W+|tr|alımlı}}, {{W+|tr|cilveli}} {{werger-bin}} 903xqvoab7pxtg4wbckncy4ql8vi7r0 hêlkan 0 50317 6347177 6346991 2026-08-30T13:45:25Z Wikihez 7344 /* Werger */ [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347177 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === [[Wêne:Little girl on swing.jpg|thumb|keçikek di hêlkanekê de]] {{navdêr|ku|z=m}} # [[rûniştek|Rûnişteka]] ku bi [[werîs]]an yan [[zincîr]]an bi [[dar]]ekê yan çend daran ve hatiye [[hilawîstin]] û mirov xwe tê de [[hejandin|dihejîne]]. #: {{hevmane|ku|hêsk|colane|dêdik|deydik|dolîdank|hêlane|hêlanek|hêlanok|hêlekan|hêzok|çîncik|çîncîrik|çînçolek|dêdîk|deydîk}} #* {{J:Firat Cewerî:Girtî:1986|jêgirtin=Şewqa agirê sobê li dîwêr mîna '''hêlkanê''' dihejiya.}} #* {{jêder-websîte|ku|jêgirtin=Piştî van agahdariyên di derbarê Ahmet Turkî de êdî divêt mirov li ser fikir û helwêstên wî jî du gotinan bibêje ko bê ew çima di serokatiya vê (DTP) partiyê de weha mîna '''hêlkanê''' kil dibe û gah dihere û gah tê.|nivîskar=Enwer Karahan|sernav=Her û her Ahmet Turk|websîte=Nefel.com|sal=7/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |hêlekan |hêlane |hêlanok }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Bide ber ==== {{kol3|ku |colank |landik }} ==== Bi zaravayên din ==== * {{Z|ckb}}: {{W-|ckb|جۆلانه|tr=colane}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Schaukel|f}}, {{W+|de|Wippen}}, {{W|de|Schaufel|f}} * {{Z|cs}}: {{W+|cs|houpačka}} * {{Z|zh}}: {{W+|zh|秋千}} * {{Z|da}}: {{W+|da|gynge}} * {{Z|id}}: {{W+|id|ayun}}, {{W+|id|ayunan}} * {{Z|eo}}: {{W+|eo|balanco}} * {{Z|fa}}: {{W+|fa|مهد}} * {{Z|fi}}: {{W+|fi|keinu}}, {{W+|fi|kiikku}}, {{W+|fi|liekku}}, {{W+|fi|lietsu}} * {{Z|fr}}: {{W|fr|balançoire|f}} * {{Z|nl}}: {{W+|nl|schommel}} * {{Z|he}}: {{W+|he|נדנדה תלויה}} * {{Z|en}}: {{W-|en|swing}} * {{Z|is}}: {{W|is|róla|f}} * {{Z|ja}}: {{W+|ja|ブランコ}} * {{Z|ko}}: {{W-|ko|그네|tr=geune}} * {{Z|la}}: {{W+|la|cunae}} * {{Z|hu}}: {{W+|hu|hinta}} * {{Z|pl}}: {{W+|pl|huśtawka}} * {{Z|pt}}: {{W+|pt|balanço}} * {{Z|ru}}: {{W+|ru|качели}} * {{Z|es}}: {{W|es|columpio|m}}, {{W-|es|hamaca}} * {{Z|sv}}: {{W+|sv|gunga}} * {{Z|tr}}: {{W+|tr|salıncak}} * {{Z|el}}: {{W-|el|κούνια|tr=kunia}} {{werger-bin}} 9gv67z8j3s0yyochw94ovrulp2aeme0 dahêlan 0 50408 6347196 6335140 2026-08-30T15:57:17Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347196 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === {{lêker|ku|c=?}} # [[berdan]] [[jêr]], [[berdan]] [[xwar]]ê, [[avêtin]] #: {{nm|ku|Dewlikê avê '''dahêla''' binê bîrê daku tijî av bibe.}} #* {{J:Sidqî Hirorî:Kurê Zinarê Serbilind:1996|jêgirtin=Roj ava bû û şevê xwe bi ser deverê de '''dahêla'''.}} #* {{jêder|ku|Îbrahîm Remezan Zaxoyî: ''Ferhenga Pîşkên Kurdî'', weşanxaneya Spîrêz, Dihok, 2007, r. 61|jêgirtin=Xanê dewlik '''dahêla''' bîra avê bo avhilkêşanê.}} ==== Tewandin ==== :da-hêl- ==== Formên alternatîv ==== {{kol3|ku |dahiştin |dahêştin }} ==== Jê ==== {{kol3|ku |dahêlayî |dahêler |dahêlk }} ==== Etîmolojî ==== Ji {{qertaf|ku|da-|hêlan}}. ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W-|fa|پایین انداختن}}, {{W-|fa|سرازیر کردن}} * {{Z|en}}: to {{W-|en|head down}}, {{W+|en|impend|guman=erê}}, {{W+|en|loll|guman=erê}}, {{W+|en|nutate|guman=erê}}, {{W+|en|sagging|guman=erê}}, {{W+|en|suspense|guman=erê}}, {{W+|en|suspension|guman=erê}}, {{W+|en|let down|guman=erê}}, {{W+|en|prolapse|guman=erê}}, {{W+|en|swag|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Werger ==== {{werger-ser}} {{werger-bin}} btfy1a94w1yh8wnrfz425cppz9t1kns recm 0 50590 6347228 6346254 2026-08-30T18:20:21Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347228 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/rɛd͡ʒm/}} * {{kîte|ku|recm}} === Navdêr === [[Wêne:Girolamo da Treviso cat01.jpg|thumb|recimkirin]] {{navdêr|ku|z=m}} # [[kevir|Kevir]] û [[ber]] li kesekî [[ceza]]kirî dan daku ew bêt [[kuştin]]. #* {{jêder|ku|jêgirtin=Li Îranê cezayê '''recmê''' piranî ji bo cezayên zînayê tê dayîn. Mêr heta piştê û jin jî heta sîngê tê binaxkirin û piştre bi keviran lê wan tê dayîn. Lê divê kevir ne pirr mezin bin da ku ew kes [zû] nemire.|Netkurd.com, 7/2008}} # {{f|ku|mecazî}} bi [[dijwar]]î [[nefret]] kirin ==== Formên alternatîv ==== {{kol3|ku |recim }} ==== Jê ==== {{kol3|ku |recmandin |recmandî |recmî |recmîn |recmîner |recmker }} ==== Etîmolojî ==== Ji {{deyn|ar|ku|رجم}} ==== Bide ber ==== {{kol3|ku |recîm }} ==== Werger ==== {{werger-ser|bi [[kevir]] û [[ber]]an [[kuştin]]}} * {{Z|de}}: {{W-|de|Steiningung}}, {{W+|de|Steinigung|f}} * {{Z|zh}}: {{W+|zh|石刑}} * {{Z|da}}: {{W+|da|stening}} * {{Z|ar}}: {{W-|ar|رجم|tr=recm}} * {{Z|fa}}: {{W-|fa|سنگسار|tr=sengsar}} * {{Z|fi}}: {{W+|fi|kivitys}}, {{W-|fi|kivitystuomio}} * {{Z|fr}}: {{W-|fr|laptidation}} * {{Z|nl}}: {{W+|nl|steniging}} * {{Z|en}}: {{W-|en|laptidation}}, {{W+|en|stoning}} * {{Z|it}}: {{W+|it|lapidazione}} * {{Z|ja}}: [[石打ち]] (いしうち) * {{Z|ko}}: {{W-|ko|투석형}} * {{Z|no}}: {{W-|no|steining}} * {{Z|pl}}: {{W+|pl|ukamienowanie}} * {{Z|pt}}: {{W-|pt|lapidação|tr=pena de morte}} * {{Z|ro}}: {{W+|ro|lapidare}} * {{Z|ru}}: {{W-|ru|побие́ние камня́ми}} * {{Z|es}}: {{W+|es|lapidación}} * {{Z|sv}}: {{W+|sv|stening}} * {{Z|tr}}: {{W+|tr|recm}}, {{W+|tr|recim}} {{werger-bin}} paal5k4w3sh7wcp74fp3fuddtx8kk2a cebir 0 50780 6347194 6304105 2026-08-30T15:54:03Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347194 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[kewîn|Kewîn]]a [[birîn]]an, [[sax]]bûna [[birîn]]an, [[cebirîn]] yan [[cebirandin]]. #* {{jêder|ku|jêgirtin=Tadeya fizîkî ya ku lê bûye, ji laş derbasî ruhê bûye û derzeke '''bêcebir''' li ruh xistiye.|Firat Cewerî di hevpeyivînekê de li gel Murad Ciwan li ser romana xwe "Ez ê yekî bikujim", Netkurd.com, 11/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |cebr }} ==== Têkildar ==== {{kol3|ku |cebar }} ==== Etîmolojî ==== Ji {{ji|ar|ku|جبر|cuda=جَبْر}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Algebra|f}} * {{Z|fi}}: {{W+|fi|parantuminen}} * {{Z|en}}: [[heal]]ing, [[recover]]ing, [[getting]] [[better]] * {{Z|tr}}: {{W+|tr|cebir}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[zor]], [[kotek]], [[cebr]] #* {{bêmînak|tr}} tafe739slnxo5cclmxrvak3xgn0bxed 6347211 6347194 2026-08-30T17:12:09Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347211 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[kewîn|Kewîna]] [[birîn]]an, [[sax]]bûna [[birîn]]an, [[cebirîn]] yan [[cebirandin]]. #* {{jêder|ku|jêgirtin=Tadeya fizîkî ya ku lê bûye, ji laş derbasî ruhê bûye û derzeke '''bêcebir''' li ruh xistiye.|Firat Cewerî di hevpeyivînekê de li gel Murad Ciwan li ser romana xwe "Ez ê yekî bikujim", Netkurd.com, 11/2008}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Formên alternatîv ==== {{kol3|ku |cebr }} ==== Têkildar ==== {{kol3|ku |cebar }} ==== Etîmolojî ==== Ji {{ji|ar|ku|جبر|cuda=جَبْر}}. ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Algebra|f}} * {{Z|fi}}: {{W+|fi|parantuminen}} * {{Z|en}}: [[heal]]ing, [[recover]]ing, [[getting]] [[better]] * {{Z|tr}}: {{W+|tr|cebir}} {{werger-bin}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[zor]], [[kotek]], [[cebr]] #* {{bêmînak|tr}} emakrgf55kfm1mg75gakhlloaddq6w0 şûnwar 0 51178 6347193 6323320 2026-08-30T15:53:34Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347193 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[asar]], [[keleh]] û [[birc]] û [[avahî|avahiyên]] din yên [[kevnar]], [[cih]]ên [[arkeolojîk]], [[der]]ên [[dîrokî]] #* {{jêder|ku|jêgirtin=Li gorî amara Birêveberiya Şûnwarên Germiyanê, piraniya '''şûnwaran''' li sînorê bajarokê Kelarê (navenda kargêrî ya Germiyanê) û bajarokê Kifrî ne ku hejmara '''şûnwarên''' wan digihêje 244 '''şûnwaran''', li bajarokê Çemçemal û navçeyên din jî 142 '''şûnwar''' hene.|Aknews.com, 6/2011}} # [[war]]ên [[kavil]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|شوینوار}} ==== Jê ==== {{kol3|ku |şûnwargerr |şûnwargerrî |şûnwarî |şûnwarnas |şûnwarnasî |şûnwarvan |şûnwarvanî |şûnwarzan |şûnwarzanî }} ==== Etîmolojî ==== Ji {{qertaf|ku|şûn|war}}. (anku cihê warên kevn, [[şop]]a [[war]]ên [[kevn]]) ==== Bide ber ==== {{kol3|ku |şînwar |şwînwar }} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|Zuhause|m}} * {{Z|ar}}: {{W+|ar|مكان|guman=erê}}, {{W-|ar|أخلاف|guman=erê}}, {{W-|ar|الآبد|guman=erê}}, {{W-|ar|الأثر|guman=erê}}, {{W-|ar|الطلل|guman=erê}}, {{W-|ar|العفاء|guman=erê}}, {{W-|ar|العقبولة|guman=erê}}, {{W-|ar|المشر|guman=erê}}, {{W-|ar|النبث|guman=erê}}, {{W-|ar|بلقع|guman=erê}} * {{Z|fa}}: {{W-|fa|قرار گاه}}, {{W+|fa|مکان|guman=erê}}, {{W+|fa|جا|guman=erê}} * {{Z|en}}: {{W+|en|toll|guman=erê}}, {{W+|en|ruins}}, {{W-|en|archeological site}} * {{Z|tr}}: {{W+|tr|semt}}, {{W-|tr|tarihî yer}}, {{W+|tr|mesken}}, {{W+|tr|yurtluk}}, {{W+|tr|kalıntı}} {{werger-bin}} hfajanf7ndfyhe7160urcoiao6ykw1a sena 0 51188 6347212 6325092 2026-08-30T17:45:00Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347212 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{IPA|ku|/sɛˈnɑː/}} * {{kîte|ku|se|na}} === Navdêr === {{navdêr|ku|z=m}} # Bi [[qenc]]î [[behs]]ê kesekî yan tiştekî kirin. #: {{hevmane|ku|pesn|meth|hemd}} #: {{nm|ku|Pesn û '''sena''' bo Xwedê}} #: {{nm|ku|Wî gelek pesn û '''senaya''' min kir.|Wî got ku ez gelek baş im.|rêz=1}} #* {{J:Mem û Zîn:1692|jêgirtin=Kay cismê letîf ê subhetî roh!<br>Dergahê beden li ber te meftûh.<br>Ez hêvî dikim ku bê teweqquf.<br>Rencîde qedem be bê tekelluf.<br>Carek here suddetelseadet.<br>Gavek here sudretelnihayet.<br>Ewwel here bibose astanê.<br>Paşê here pêş dilistanê.<br>Emma bi tewaduî û teizîm.<br>Sed mertebe ihtiram û tekrîm.<br>Ahiste ji bo bike duayê.<br>Wa besteyî wê bike '''senayê'''.<br>Şayiste bike tu ihtiramê.<br>Destbeste vewest bike selamê.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Jê ==== {{kol3|ku |senaxwan }} ==== Etîmolojî ==== Ji {{ji|ar|ku|سناء|tr=senai}}, hevreha {{hv|arc|ܫܢܐ|tr=şenna}} ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W+|fa|ثنا|guman=erê}} * {{Z|tr}}: {{W+|tr|övgü}}, {{W+|tr|sena}} {{werger-bin}} == {{ziman|mt}} == === Navdêr === {{navdêr|mt|z=m}} # {{f|mt|dem}} [[sal#ku|sal]] #* {{bêmînak|mt}} == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[pesn]], [[sena]] #* {{bêmînak|tr}} bapvwulfqdhxoc1bmv4z3h9ti6i25ft norandin 0 51251 6347186 6313567 2026-08-30T13:58:14Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347186 wikitext text/x-wiki {{ds|nehwirandin|norandin}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{ku-tewîn-lk|norandin|form=gerguhêz|niha=norîn|borî=norand}} {{lêker|ku|c=x-gh}} # Bi dengek [[nizm]] [[strîn]] yan [[peyivîn]]; bo xwe [[peyivîn]] yan [[stran]] [[gotin]]. #: {{hevmane|ku|lobandin|nehwirandin|nêwirandin|nûhirandin|tewirandin}} #* {{jêder|ku|Arjen Arî, Helbest, û welaté ku ez jé, welateme.info, 11.08.2009|jêgirtin=Ez ji wî welatî me, ji wî welaté ku çiyayén wé helbestén evînén bémirad '''dinehwirînin''' û digorînin di ber xwe de.}} #* {{jêder|ku|çarînek ji helbest SIRA SIBE ya Rojen BARNAS|jêgirtin=Kaniya bin dara hewrê/ Bi dengê bilurê re '''nehwirand'''/ Hêstir werwirand melûl melûl/ Dilê heyva ji kovanên xwe re/ Kerî bi kerî kezext û dirand}} ==== Tewandin ==== ''Lêker'': :-norîn- ==== Bi alfabeyên din ==== * {{ku-ar|نۆراندن}} ==== Formên alternatîv ==== {{kol3|ku |nuhirandin |nuhrandin |nûrandin }} ==== Jê ==== {{kol3|ku |norandî |norîner |norînk }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|falten}}, {{W+|de|trällern}} * {{Z|en}}: {{W-|en|to murmur}}, {{W-|en|to mumble}}, {{W-|en|to mutter}}, {{W+|en|mumble}} * {{Z|tr}}: {{W+|tr|mırıldamak}}, {{W+|tr|terennüm etmek}}, {{W+|tr|bükmek}}, {{W+|tr|devşirmek}}, {{W+|tr|dürmek}}, {{W+|tr|katlama}}, {{W+|tr|katlamak}}, {{W+|tr|katlayış}}, {{W+|tr|kıvırma}}, {{W+|tr|kıvırmak}}, {{W+|tr|mırıldama}}, {{W+|tr|bükme}}, {{W-|tr|şarkı mırıldanmak|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} lqy6finwj92khr0383gwfybudcs6zl0 6347187 6347186 2026-08-30T13:59:24Z Wikihez 7344 /* Tewandin */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347187 wikitext text/x-wiki {{ds|nehwirandin|norandin}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{ku-tewîn-lk|norandin|form=gerguhêz|niha=norîn|borî=norand}} {{lêker|ku|c=x-gh}} # Bi dengek [[nizm]] [[strîn]] yan [[peyivîn]]; bo xwe [[peyivîn]] yan [[stran]] [[gotin]]. #: {{hevmane|ku|lobandin|nehwirandin|nêwirandin|nûhirandin|tewirandin}} #* {{jêder|ku|Arjen Arî, Helbest, û welaté ku ez jé, welateme.info, 11.08.2009|jêgirtin=Ez ji wî welatî me, ji wî welaté ku çiyayén wé helbestén evînén bémirad '''dinehwirînin''' û digorînin di ber xwe de.}} #* {{jêder|ku|çarînek ji helbest SIRA SIBE ya Rojen BARNAS|jêgirtin=Kaniya bin dara hewrê/ Bi dengê bilurê re '''nehwirand'''/ Hêstir werwirand melûl melûl/ Dilê heyva ji kovanên xwe re/ Kerî bi kerî kezext û dirand}} ==== Tewandin ==== :-norîn- ==== Bi alfabeyên din ==== * {{ku-ar|نۆراندن}} ==== Formên alternatîv ==== {{kol3|ku |nuhirandin |nuhrandin |nûrandin }} ==== Jê ==== {{kol3|ku |norandî |norîner |norînk }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W+|de|falten}}, {{W+|de|trällern}} * {{Z|en}}: {{W-|en|to murmur}}, {{W-|en|to mumble}}, {{W-|en|to mutter}}, {{W+|en|mumble}} * {{Z|tr}}: {{W+|tr|mırıldamak}}, {{W+|tr|terennüm etmek}}, {{W+|tr|bükmek}}, {{W+|tr|devşirmek}}, {{W+|tr|dürmek}}, {{W+|tr|katlama}}, {{W+|tr|katlamak}}, {{W+|tr|katlayış}}, {{W+|tr|kıvırma}}, {{W+|tr|kıvırmak}}, {{W+|tr|mırıldama}}, {{W+|tr|bükme}}, {{W-|tr|şarkı mırıldanmak|guman=erê}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{mane?|ku}} #* {{bênimûne|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} e2h2x1vu9i7cb5i3jlm0dx054dwyoga dîskrîmînasyon 0 51374 6347192 6305763 2026-08-30T15:52:33Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347192 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[ferq|Ferq]] û [[cudahî]] xistin navbera mirovan; hemû mirov wek hev ne[[hesibandin]]; [[miamele]]ya [[wekhev]] li gel hemû kesan nekirin #: {{nm|ku|Li Tirkiyê '''dîskrîmînasyon''' li dijî kurdan serdest e.|Kurd li Tirkiyê wek tirkan baş nayên hesibandin.|rêz=1}} #: {{nm|ku|Li gelek welatan '''dîskrîmînasyona''' dijî jinan didome.|Ew wek mêran baş nayên hesibandin.|rêz=1}} #* {{jêder|ku|jêgirtin=Peymana rakirina hemû awayên '''dîskrîmînasyona''' jinan|http://wikisource.org/wiki/Peymana_rakirina_hem%C3%BB_away%C3%AAn_d%C3%AEskr%C3%AEm%C3%AEnasyona_jinan}} # [[vewêrtin]] #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Têkildar ==== {{kol3|ku |dîskrîmînatîf |dîskrîmînatîv |dîskrîmînator |dîskrîmîne }} ==== Etîmolojî ==== Bi rêya {{ji|fr|ku|discrimination}}, ji {{ji|la|ku|discriminatus}} ji [[discriminare]] ji [[discrimen]] ([[cudahî]]) ==== Werger ==== {{werger-ser}} * {{Z|de}}: {{W|de|Diskriminierung|f|guman=erê}} * {{Z|fi}}: {{W+|fi|syrjintä}} * {{Z|fr}}: {{W+|fr|discrimination}} * {{Z|en}}: {{W+|en|discrimination}}, {{W+|en|apartheid}} * {{Z|tr}}: {{W+|tr|diskriminasyon}} {{werger-bin}} cnjeu1luea5y3vf0wb15sza2ascwfbo pêxwarin 0 52216 6347244 6315144 2026-08-30T18:47:45Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347244 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{navdêr|ku|z=m}} # Tişta/ê ku mirov [[li gel]] [[nan]]î [[xwarin|dixwe]] (bo nimûne: [[mast]] û [[penîr]]). #* {{jêder|ku|Silêman Feqiyanî, Yuksekovahaber.com, 7/2009|jêgirtin=Dil sotin û dilkeseriya jiyanê, kul û kovaniyên jiyanê, kerb û xwîndariya jiyanê, çavsorî û hesûdiya jiyanê, dewlemendî û xizanîya jiyanê, hêvî û daxwazên jiyanê, evînî û hezkirina jiyanê, keser û kulilkên jiyanê, şîn û taziyên jiyanê, kenî û giriyên jiyanê, silh û mesilhetên jiyanê, xem û xiyalên jiyanê, jehr û ziqqûma jiyanê, mewt û pêmirina jiyanê, serece û taştîkên jiyanê, kezab û qulquleya jiyanê di hindirê xwe de veşêrî.}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|پێخوارن}} ==== Têkildar ==== {{kol3|ku |spiyatî }} ==== Etîmolojî ==== Ji {{qertaf|ku|pê<t:bi wê>|xwarin}}. ==== Bide ber ==== {{kol3|ku |pêmirin }} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|الإدام|guman=erê}}, {{W-|ar|الأدم|guman=erê}}, {{W-|ar|الصبـغ|guman=erê}}, {{W-|ar|الصبغة|guman=erê}}, {{W-|ar|المري|guman=erê}}, {{W-|ar|كامخ|guman=erê}} * {{Z|en}}: something eaten with one's [[bread]] (e.g. cheese, {{W+|en|yoghurt}}, olives etc.) * {{Z|tr}}: {{W+|tr|katık}} {{werger-bin}} b65tgge5vuyrw25r6tcrq3xp02ta6ol 6347245 6347244 2026-08-30T18:48:45Z Wikihez 7344 kelîme derbas nabe 6347245 wikitext text/x-wiki == {{ziman|ku}} == === Navdêr === {{navdêr|ku|z=m}} # Tişta/ê ku mirov [[li gel]] [[nan]]î [[xwarin|dixwe]] (bo nimûne: [[mast]] û [[penîr]]). ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|پێخوارن}} ==== Têkildar ==== {{kol3|ku |spiyatî }} ==== Etîmolojî ==== Ji {{qertaf|ku|pê<t:bi wê>|xwarin}}. ==== Bide ber ==== {{kol3|ku |pêmirin }} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|الإدام|guman=erê}}, {{W-|ar|الأدم|guman=erê}}, {{W-|ar|الصبـغ|guman=erê}}, {{W-|ar|الصبغة|guman=erê}}, {{W-|ar|المري|guman=erê}}, {{W-|ar|كامخ|guman=erê}} * {{Z|en}}: something eaten with one's [[bread]] (e.g. cheese, {{W+|en|yoghurt}}, olives etc.) * {{Z|tr}}: {{W+|tr|katık}} {{werger-bin}} 76k7krv8baut7ebkf2um2tsm0fiwq96 jealous 0 56792 6347321 6085690 2026-08-31T08:21:31Z Joseph Hemê 2610 /* Rengdêr */ 6347321 wikitext text/x-wiki == {{ziman|en}} == === Bilêvkirin === :{{ku-tîp|cêlis}} * {{deng|en|en-us-jealous.ogg|dever=DYA}} * {{deng|en|LL-Q1860 (eng)-Vealhurl-jealous.wav|Deng|dever=Başûrê Îngilistanê, QY}} * {{deng|en|LL-Q1860 (eng)-Wodencafe-jealous.wav|Deng|dever=Teksas, DYA}} * {{deng|en|LL-Q1860 (eng)-Grendelkhan-jealous.wav|Deng|dever=Connecticut, DYA}} === Rengdêr === {{rengdêr|en}} # [[çavnebar]], [[hesûd]], [[jêlûs]]. #* {{bêmînak|en}} gcbkdaqr0kgb2tokfo4jbp98ot7umku kortal 0 61579 6347180 6346988 2026-08-30T13:46:20Z Wikihez 7344 [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347180 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[cih|Cihên]] ku ji [[derdor]]ên xwe [[kûr]]tir / [[nizm]]tir in. #: {{hevmane|ku|çal|korm|krater|kort|zûng}} #* {{jêder|ku|jêgirtin=Û hevalê kimtên wan<br>yên bi mij û dûman,<br>û tê de dengê xwe berdin,<br>û zarîna dengê me<br>bikeve nav '''kortal''' û geliyan<br>û bêcaniya erdên jêrîn <br>bihejîne;<br>û pêlên ava heftreng<br>ên xemzebaz<br>nalîna me bigehîne<br>deşta Sirûç û Diyarbekrê;<br>û beriya mêrxasên Berazan;<br>û kalîna berxan<br>tev şehîna hespan<br>li me vegerînin.|Celadet Bedirxan: ''Bilûra min''}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Jê ==== {{kol3|ku |kortalgeh |kortalî }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{kontrolWerger}} {{werger-ser}} * {{Z|fa}}: {{W+|fa|دره}}, {{W+|fa|گودال عمیق}} * {{Z|en}}: {{W|en|hiatus}} * {{Z|tr}}: {{W+|tr|çökek}}, {{W+|tr|çukur}}, {{W+|tr|oyuntu}}, {{W+|tr|yarıntı}}, {{W+|tr|ineç}}, {{W+|tr|krater}}, {{W+|tr|uçurum}}, {{W+|tr|düden}}, {{W|tr|havza|guman=erê}} {{werger-bin}} rsfa0ybl6g3q7khq8bdrpmpowjw1ahc فرمان 0 61996 6347260 5883717 2026-08-30T20:44:02Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347260 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === :firman === Navdêr === {{navdêr|ku|sc=Arab|z=m}} # [[ferman]], [[emir]] ==== Hewiha ==== * {{g|ku|فه‌رمان}} == {{ziman|ckb}} == === Bilêvkirin === :firman === Navdêr === {{navdêr|ckb}} # [[ferman]], [[emir]] # {{f|ckb|rêziman}} [[fîil]], [[lêker]] ==== Hewiha ==== * {{g|ckb|فه‌رمان}} == {{ziman|fa}} == === Bilêvkirin === * ferman === Navdêr === {{navdêr|fa|tr=}} # [[ferman]], [[emir]] 47nystwizb5dtp2us9m0z5kjy723mnq cobar 0 62789 6347175 6346922 2026-08-30T13:44:10Z Wikihez 7344 /* Navdêr */ sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347175 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[robar]], [[co]], [[herik]]a [[av]]ê, [[celal]], [[çem]]ên [[biçûk]], [[lehî]] #* {{J:Mem û Zîn:1692|jêgirtin=Ev mêwe li kî cihî gehane?<br>Ev gul di çi gulsenê numane?<br>Serwêd çi '''cobarekî''' ne?<br>Teyrêd çi merxezarekî ne?}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|جۆبار}} ==== Jê ==== {{kol3|ku |cobarî }} ==== Etîmolojî ==== Ji {{paş|ku|co|-bar}} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|الجعفر|guman=erê}}, {{W-|ar|جدول|guman=erê}}, {{W-|ar|میثب|guman=erê}} * {{Z|en}}: {{W+|en|torrent}}, {{W+|en|stream}}, {{W+|en|sluice|guman=erê}} * {{Z|tr}}: {{W+|tr|dere}} {{werger-bin}} 9v9rxbmtxo9zbh73p35vxpovt6161if diğer 0 132743 6347173 6075216 2026-08-30T12:02:06Z Rewiye tine 7120 6347173 wikitext text/x-wiki == {{ziman|tr}} == === Daçek === {{daçek|tr}} # [[din]] # [[dîtir]], [[diğer]], [[dike]], [[dîtirk]], [[a din]], ê din, [[dî]] #: {{mk|tr|sen değil '''diğeri''' gelsin|rêz=1| tu na, bila yê din bê }} 6x94nui186belbv3t6ul25uwvwyggci erirlik 0 135032 6347325 4610309 2026-08-31T09:42:43Z Wikihez 7344 guhartina pêşketî (DefSideBoxes) (bi alîkarî) 6347325 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[pile|pileya]] [[hetan|hetanê]] lp2qtgwlonk08i6w8bkclc1eox6ocbd 6347339 6347325 2026-08-31T11:12:15Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347339 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[pile]]ya [[hetan]]ê 0avfgcdl8bqigc3xl6qv3s4chkfe7wz delîn 0 178799 6347181 6346999 2026-08-30T13:46:42Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347181 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=ngh}} # [[çav li rê bûn]] # [[kamsojkî bûn]] # [[bêtaqet bûn]], [[ji hal ketin]], [[ji qudûm ketin]], [[delandin]] #* {{jêder-kitêb|ku|nivîskar=w:Çerkezê Reş|sernav=Şorişa Xebera (helbest)|cih=Yêrêvan|sal=1986|jg=Lawkê min nehat, lawkê min nehat,<br>Êvara şeva lawkê min nehat,<br>Ax '''deliyan''', biriyan îlik û qewat,<br>Xewa dil seva lawkê min nehat!}} # [[mirin]] (ji ber birçîbûnê, tîbûnê, hesretê, çaverê hwd.) #* {{jêder-kitêb|ku|nivîskar=w:Şikoyê Hesen|sernav=Perweza Weten|cih=Yêrêvan|sal=1977|jg=Derdê ‘îsên nolî bûzê li ber te‘va nuh heliya,<br>Zulm-hêsîriyê bask şikestin, ketin gorrê û '''deliyan'''.}} #* {{jêder-kitêb|ku|nivîskar=w:Fêrîkê Ûsiv|sernav=BIJARE|weşanxane=Weşanxana "Lêgal Plyûs"|cih=Yêrêvan|sal=2010|jg=Û çirave av naçe ser ehliya,<br>Ehilî tîbûna zûriqî, '''deliya'''.}} ==== Tewandin ==== : [[-del-]] ==== Bi alfabeyên din ==== * {{ku-ar|ده‌لین}} ==== Têkildar ==== {{kol3|ku |delandin }} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|fa}}: {{W|fa|منتظر بودن}} * {{Z|en}}: {{W|en|infiltration}}, {{W|en|leak}}, {{W|en|percolation}}, {{W|en|permeation}}, {{W|en|leach|guman=erê}}, {{W|en|osmosis|guman=erê}} * {{Z|tr}}: {{W|tr|çatal görmek}}, {{W|tr|karıkmak}}, {{W|tr|kamaşma}}, {{W|tr|karıkma}}, * {{Z|tr}}: {{W|tr|takatsiz kalmak}}, {{W|tr|yorgun düşmek}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # {{bêwate|ku}} #* {{bêmînak|ku}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} 526qgct5m2cq6i91k3hgzwhp98c5ii6 tûjandin 0 266260 6347198 6319595 2026-08-30T16:01:23Z Wikihez 7344 sererastkirina nimûneyên edebiyatê (bi destî) [[Wîkîpediya:AutoWikiBrowser|AWB]] 6347198 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên tûjandin û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye '''tujandin'''.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Bi alfabeyên din ==== * {{ku-ar|تووژاندن}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|التحري|guman=erê}}, {{W-|ar|التحقیـق|guman=erê}} * {{Z|en}}: {{W+|en|ascertain}} * {{Z|tr}}: {{W+|tr|tahkik etmek}}, {{W-|tr|tahkik yapmak}} {{werger-bin}} === Çavkanî === * {{Ferhenga Kamêran}} 4pw4xar5y941weogx97yxeozv1dbmre 6347199 6347198 2026-08-30T16:02:57Z Wikihez 7344 6347199 wikitext text/x-wiki == {{ziman|ku}} == === Bi alfabeyên din === * {{ku-ar|تووژاندن}} === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên tûjandin û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye '''tujandin'''.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|التحري|guman=erê}}, {{W-|ar|التحقیـق|guman=erê}} * {{Z|en}}: {{W+|en|ascertain}} * {{Z|tr}}: {{W+|tr|tahkik etmek}}, {{W-|tr|tahkik yapmak}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} === Çavkanî === * {{Ferhenga Kamêran}} bbo7bw78tdfe66opus1uxm4b3zz5ytp 6347200 6347199 2026-08-30T16:03:39Z Wikihez 7344 6347200 wikitext text/x-wiki == {{ziman|ku}} == === Bi alfabeyên din === * {{ku-ar|تووژاندن}} === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên tûjandin û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye '''tujandin'''.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|التحري|guman=erê}}, {{W-|ar|التحقیـق|guman=erê}} * {{Z|en}}: {{W+|en|ascertain}} * {{Z|tr}}: {{W+|tr|tahkik etmek}}, {{W-|tr|tahkik yapmak}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên '''tûjandin''' û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye tujandin.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} === Çavkanî === * {{Ferhenga Kamêran}} pzyo51fej5i8sthjkb7moybz9qicxx9 6347201 6347200 2026-08-30T16:04:03Z Wikihez 7344 /* Lêker */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347201 wikitext text/x-wiki == {{ziman|ku}} == === Bi alfabeyên din === * {{ku-ar|تووژاندن}} === Bilêvkirin === * {{ku-kîte}} === Lêker === {{lêker|ku|c=}} # [[lêgeran]], li pey geran, [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên tûjandin û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye '''tujandin'''.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} * {{Z|ar}}: {{W-|ar|التحري|guman=erê}}, {{W-|ar|التحقیـق|guman=erê}} * {{Z|en}}: {{W+|en|ascertain}} * {{Z|tr}}: {{W+|tr|tahkik etmek}}, {{W-|tr|tahkik yapmak}} {{werger-bin}} === Navdêr === {{navdêr|ku|z=m}} # [[lêgeran]], li pey geran, [[dîvçûv]], [[vekolîn]] #* {{jêder|ku|jg=Gelekan jî ev zanyarên şaş di kitêb û nivîsarên paştir da dubare û çendbare kirine. Heta vê gavê jî dîwaneka bê şaşî û dirist jî çap nebûye. Li goreyê şêwazên '''tûjandin''' û vejandina destxetên kevin, hêşta jî Dîwan bi dirstî nehatiye tujandin.|Lezgîn Çalî; nivîsa (Rêzimana Dîwana Melayê Cizîrî}} ==== Tewandin ==== {{ku-tewîn-nav|mê}} ==== Etîmolojî ==== {{bêetîmolojî|ku}} ==== Werger ==== {{werger-ser}} {{werger-bin}} === Çavkanî === * {{Ferhenga Kamêran}} paqhmd5y2xw8b5l9i608ih4u1iytwvl کتێب 0 270711 6347277 6340602 2026-08-30T22:27:09Z Wikihez 7344 +nimûneya bikaranînê bi amûra « [[Mediawiki:Gadget-wikt.add-examples|Nimûne zêde bike]] » (v2.0). 6347277 wikitext text/x-wiki == {{ziman|ckb}} == === Bilêvkirin === * {{ckb-IPA|kitêb}} === Navdêr === [[Wêne:Old books - Stories From The Past.jpg|thumb|{{g|ckb||'''کتێبانی''' کۆن|tr='''Kitêbanî''' kon|w=Kitêbine kevn}}]] {{navdêr|ckb|tr=kitêb}} # [[pirtûk]], [[kitêb]], [[kîtab]] #* {{hevmane|ckb|پەڕتووک}} #* {{jêder-websîte|ckb|nivîskar=@vanabook97|sernav=Vana-Sûra|websîte=Twitter|url=https://x.com/vanabook97/status/2088998525363159429|tarîx=2026-08-16|jêgirtin=دەستمکرد بەخوێندنەوەی ئەم '''کتێبە:''' بە دەم ڕێگاوە گوڵچنین |tr=Destim kird be xwêndinewey em '''kitêbe''': Be dem řêgawe guɫçinîn. |w=Min dest bi xwendina vê kitêbê kir: Li ser rê gulçinîn.}} #* {{jêder-kitêb|ckb|nivîskar=w:Mihemed Emîn Zekî|sernav=ckb:خولاسەیەکی تاریخی کورد و کوردستان (جڵدی ٢)<tr:Xulaseyekî Tarîxî Kurd û Kurdistan (Cildî 2)>|sal=1931|url=https://books.vejin.net/ck/text/28436|jêgirtin='''کتێبی''' تاریخی موئەریخینیش ئەڵێ: لە خسووسی سەلاحەددینەوە ئەوەی کە مەسیحییەکانی تووشی دەهشەت و حیرەت کردبوو، مورووەت و عولووی جەنابی، سەخا و کەرەمی، ڕەحم و حیلمی، لێبوردن و عەفووکردنی و باخسووس ڕیعایەتی عەهد و پەیمانی بوو، بەڕاستی زۆر مەوجیبی حیرەتە کە ئەم هەموو ئەوسافە بڵیندە، کە دڵی ئەورووپاییەکانی پڕ لە تەقدیر و تەبجیل کردبوو، هەموو ئەمانە وەسفی زاتێکی وایە کە غەلەبەی بە سەریانا کردووە و لە ئاسیای دەرپەڕاندوون.|tr=kitêbî tarîxî mu’erîxînîş ełê: le xisûsî selaḧeddînewe ewey ke mesîḧîyekanî tûşî dehşet û ḧîret kirdibû, muruwet û ’ulûy cenabî, sexa û keremî, řeḧim û ḧîlmî, lêburdin û ’efûkirdinî û baxsûs řî’ayetî ’ehd û peymanî bû, beřastî zor mewcîbî ḧîrete ke em hemû ewsafe biłînde, ke diłî ewrûpayyekanî piř le teqdîr û tebcîl kirdibû, hemû emane wesfî zatêkî waye ke ẍelebey be seryana kirduwe û le asyay derpeřandûn.}} ==== Formên alternatîv ==== * {{hw|ckb|کتێو|tr=kitêw}} * {{hw|ckb|کتاو|tr=kitaw}} ==== Jê ==== {{col3|ckb | کتێبخانە<tr:kitêbxane> | کتێبفرۆش<tr:kitêbfiroş> }} ==== Etîmolojî ==== Ji {{deyn|ar|ckb|كِتَاب|}}. izqg8qh6zlwr463t07x0oz99gw9ed7d 6347278 6347277 2026-08-30T22:28:16Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347278 wikitext text/x-wiki == {{ziman|ckb}} == === Bilêvkirin === * {{ckb-IPA|kitêb}} === Navdêr === [[Wêne:Old books - Stories From The Past.jpg|thumb|{{g|ckb||'''کتێبانی''' کۆن|tr='''Kitêbanî''' kon|w=Kitêbine kevn}}]] {{navdêr|ckb|tr=kitêb}} # [[pirtûk]], [[kitêb]], [[kîtab]] #* {{hevmane|ckb|پەڕتووک}} #* {{jêder-kitêb|ckb|nivîskar=w:Mihemed Emîn Zekî|sernav=ckb:خولاسەیەکی تاریخی کورد و کوردستان (جڵدی ٢)<tr:Xulaseyekî Tarîxî Kurd û Kurdistan (Cildî 2)>|sal=1931|url=https://books.vejin.net/ck/text/28436|jêgirtin='''کتێبی''' تاریخی موئەریخینیش ئەڵێ: لە خسووسی سەلاحەددینەوە ئەوەی کە مەسیحییەکانی تووشی دەهشەت و حیرەت کردبوو، مورووەت و عولووی جەنابی، سەخا و کەرەمی، ڕەحم و حیلمی، لێبوردن و عەفووکردنی و باخسووس ڕیعایەتی عەهد و پەیمانی بوو، بەڕاستی زۆر مەوجیبی حیرەتە کە ئەم هەموو ئەوسافە بڵیندە، کە دڵی ئەورووپاییەکانی پڕ لە تەقدیر و تەبجیل کردبوو، هەموو ئەمانە وەسفی زاتێکی وایە کە غەلەبەی بە سەریانا کردووە و لە ئاسیای دەرپەڕاندوون.|tr=kitêbî tarîxî mu’erîxînîş ełê: le xisûsî selaḧeddînewe ewey ke mesîḧîyekanî tûşî dehşet û ḧîret kirdibû, muruwet û ’ulûy cenabî, sexa û keremî, řeḧim û ḧîlmî, lêburdin û ’efûkirdinî û baxsûs řî’ayetî ’ehd û peymanî bû, beřastî zor mewcîbî ḧîrete ke em hemû ewsafe biłînde, ke diłî ewrûpayyekanî piř le teqdîr û tebcîl kirdibû, hemû emane wesfî zatêkî waye ke ẍelebey be seryana kirduwe û le asyay derpeřandûn.}} #* {{jêder-websîte|ckb|nivîskar=@vanabook97|sernav=Vana-Sûra|websîte=Twitter|url=https://x.com/vanabook97/status/2088998525363159429|tarîx=2026-08-16|jêgirtin=دەستمکرد بەخوێندنەوەی ئەم '''کتێبە:''' بە دەم ڕێگاوە گوڵچنین |tr=Destim kird be xwêndinewey em '''kitêbe''': Be dem řêgawe guɫçinîn. |w=Min dest bi xwendina vê kitêbê kir: Li ser rê gulçinîn.}} ==== Formên alternatîv ==== * {{hw|ckb|کتێو|tr=kitêw}} * {{hw|ckb|کتاو|tr=kitaw}} ==== Jê ==== {{col3|ckb | کتێبخانە<tr:kitêbxane> | کتێبفرۆش<tr:kitêbfiroş> }} ==== Etîmolojî ==== Ji {{deyn|ar|ckb|كِتَاب|}}. 3alwf3jse4kx5zfg6x6kk9pc23rny3v 6347297 6347278 2026-08-30T23:54:14Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347297 wikitext text/x-wiki == {{ziman|ckb}} == === Bilêvkirin === * {{ckb-IPA|kitêb}} === Navdêr === [[Wêne:Old books - Stories From The Past.jpg|thumb|{{g|ckb||'''کتێبانی''' کۆن|tr='''Kitêbanî''' kon|w=Kitêbine kevn}}]] {{navdêr|ckb|tr=kitêb}} # [[pirtûk]], [[kitêb]], [[kîtab]] #: {{hevmane|ckb|پەڕتووک}} #* {{jêder-kitêb|ckb|nivîskar=w:Mihemed Emîn Zekî|sernav=ckb:خولاسەیەکی تاریخی کورد و کوردستان (جڵدی ٢)<tr:Xulaseyekî Tarîxî Kurd û Kurdistan (Cildî 2)>|sal=1931|url=https://books.vejin.net/ck/text/28436|jêgirtin='''کتێبی''' تاریخی موئەریخینیش ئەڵێ: لە خسووسی سەلاحەددینەوە ئەوەی کە مەسیحییەکانی تووشی دەهشەت و حیرەت کردبوو، مورووەت و عولووی جەنابی، سەخا و کەرەمی، ڕەحم و حیلمی، لێبوردن و عەفووکردنی و باخسووس ڕیعایەتی عەهد و پەیمانی بوو، بەڕاستی زۆر مەوجیبی حیرەتە کە ئەم هەموو ئەوسافە بڵیندە، کە دڵی ئەورووپاییەکانی پڕ لە تەقدیر و تەبجیل کردبوو، هەموو ئەمانە وەسفی زاتێکی وایە کە غەلەبەی بە سەریانا کردووە و لە ئاسیای دەرپەڕاندوون.|tr=kitêbî tarîxî mu’erîxînîş ełê: le xisûsî selaḧeddînewe ewey ke mesîḧîyekanî tûşî dehşet û ḧîret kirdibû, muruwet û ’ulûy cenabî, sexa û keremî, řeḧim û ḧîlmî, lêburdin û ’efûkirdinî û baxsûs řî’ayetî ’ehd û peymanî bû, beřastî zor mewcîbî ḧîrete ke em hemû ewsafe biłînde, ke diłî ewrûpayyekanî piř le teqdîr û tebcîl kirdibû, hemû emane wesfî zatêkî waye ke ẍelebey be seryana kirduwe û le asyay derpeřandûn.}} #* {{jêder-websîte|ckb|nivîskar=@vanabook97|sernav=Vana-Sûra|websîte=Twitter|url=https://x.com/vanabook97/status/2088998525363159429|tarîx=2026-08-16|jêgirtin=دەستمکرد بەخوێندنەوەی ئەم '''کتێبە:''' بە دەم ڕێگاوە گوڵچنین |tr=Destim kird be xwêndinewey em '''kitêbe''': Be dem řêgawe guɫçinîn. |w=Min dest bi xwendina vê kitêbê kir: Li ser rê gulçinîn.}} ==== Formên alternatîv ==== * {{hw|ckb|کتێو|tr=kitêw}} * {{hw|ckb|کتاو|tr=kitaw}} ==== Jê ==== {{col3|ckb | کتێبخانە<tr:kitêbxane> | کتێبفرۆش<tr:kitêbfiroş> }} ==== Etîmolojî ==== Ji {{deyn|ar|ckb|كِتَاب|}}. pinuc0kxxf4f5e7luawedyofctfiht6 saccharimeter 0 276818 6347334 5730744 2026-08-31T10:28:28Z Wikihez 7344 guhartina pêşketî (DefSideBoxes) 6347334 wikitext text/x-wiki == {{ziman|en}} == === Navdêr === {{navdêr|en}} # [[halet|haleta]] ku [[rêje|rêjeya]] [[şekir|şekir]] ya di [[nav|nêv]] [[têkelang|têkelangekî]] de [[dipîve|dipîve]] tuaguil77c5s27buea6tm98cngehxpw toxt 0 342743 6347293 6327163 2026-08-30T23:39:10Z Wikihez 7344 guhertina maneyê (DefSideBoxes) 6347293 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Zugochsen.jpg|thumb|du gayên bi nîr]] {{navdêr|ku|z=n}} # [[dar|Dar]]ê ku du [[ga]] û [[gamêş]] pê tên [[zeft]]kirin dema [[cot]] pê tê kirin yan [[erebe]] pê tê [[kêşan]]. # {{f|ku|mecazî}} [[zilm]], [[zordestî]], [[stem]], [[bindestî]], [[koletî]] ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|نیر}} ==== Têkildar ==== * {{g|ku|basole}} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|نیر}} (nîr), [[kurdiya başûrî]] ''nîr'', [[nîre]], zazakî [[nîre]], hemû ji {{ji|ar|ku|نير|tr=nîr}}, [[hevreh]]a îbrî [[ניר]] (nîr), aramî [[ܢܝܪܐ]] (nîra), akadî ''nîru'' [http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=6896&language=id]. hevwateya wê ya ji proto-hindûewropî anku "yox / yok" di farisî û gelek zimanên din yên hindûewropî de maye (li beşa wergeran binêrin) lê ji kurdî ketiye. [[hevwate|Hevwateya]] wê ya tirkî [[boyunduruk]] jî wek [[bandor]] ketiye zimanê nivîskî yê kurdî û di kurdî de maneya "[[tesîr]]" wergirtiye. ==== Bide ber ==== {{kol3|ku |bîr |çîr |dîr |gîr |hîr |jîr |kîr |lîr |mîr |pîr |sîr |şîr |tîr |zîr }} ==== Herwiha binêre ==== {{kol3|ku |nar |nêr |nor |nûr }} ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|zgjedhë}} {{mê}} * {{Z|de}}: {{W+|de|Joch}} {{nt}} * {{Z|cs}}: {{W+|cs|jařmo}} {{nt}} * {{Z|da}}: {{W+|da|åg}} * {{Z|eo}}: {{W+|eo|jugo}} * {{Z|et}}: {{W+|et|ike}} * {{Z|fa}}: {{W+|fa|یوغ}}, {{W+|fa|یوغ}} * {{Z|fi}}: {{W+|fi|ies}} * {{Z|fr}}: {{W+|fr|joug}} {{n}} * {{Z|ang}}: {{W-|ang|geoc}} * {{Z|en}}: {{W+|en|yoke}} * {{Z|it}}: {{W+|it|giogo}} {{n}} * {{Z|ca}}: {{W+|ca|jou}} {{nt}} * {{la}} [[iugum]] {{n}} * {{Z|hu}}: {{W+|hu|iga}}, {{W+|hu|járom}} * {{Z|sh}}: {{W+|sh|igo}} {{nt}}, {{W+|sh|jaram}} {{n}} * {{Z|sk}}: {{W-|sk|jarmo}} {{nt}} * {{Z|es}}: {{W+|es|yugo}} {{n}} * {{Z|sv}}: {{W+|sv|ok}} {{nt}} * {{Z|tr}}: {{W+|tr|boyunduruk}} {{werger-bin}} t8tvf66qx678o9dfaents72ka5bqs2s 6347294 6347293 2026-08-30T23:39:41Z Wikihez 7344 +Hevmane (DefSideBoxes) 6347294 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Zugochsen.jpg|thumb|du gayên bi nîr]] {{navdêr|ku|z=n}} # [[dar|Dar]]ê ku du [[ga]] û [[gamêş]] pê tên [[zeft]]kirin dema [[cot]] pê tê kirin yan [[erebe]] pê tê [[kêşan]]. #: {{hevmane|ku|yûx|cûx|nîr}} # {{f|ku|mecazî}} [[zilm]], [[zordestî]], [[stem]], [[bindestî]], [[koletî]] ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|نیر}} ==== Têkildar ==== * {{g|ku|basole}} ==== Etîmolojî ==== Hevreha soranî {{g|ckb|نیر}} (nîr), [[kurdiya başûrî]] ''nîr'', [[nîre]], zazakî [[nîre]], hemû ji {{ji|ar|ku|نير|tr=nîr}}, [[hevreh]]a îbrî [[ניר]] (nîr), aramî [[ܢܝܪܐ]] (nîra), akadî ''nîru'' [http://www.assyrianlanguages.org/akkadian/dosearch.php?searchkey=6896&language=id]. hevwateya wê ya ji proto-hindûewropî anku "yox / yok" di farisî û gelek zimanên din yên hindûewropî de maye (li beşa wergeran binêrin) lê ji kurdî ketiye. [[hevwate|Hevwateya]] wê ya tirkî [[boyunduruk]] jî wek [[bandor]] ketiye zimanê nivîskî yê kurdî û di kurdî de maneya "[[tesîr]]" wergirtiye. ==== Bide ber ==== {{kol3|ku |bîr |çîr |dîr |gîr |hîr |jîr |kîr |lîr |mîr |pîr |sîr |şîr |tîr |zîr }} ==== Herwiha binêre ==== {{kol3|ku |nar |nêr |nor |nûr }} ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|zgjedhë}} {{mê}} * {{Z|de}}: {{W+|de|Joch}} {{nt}} * {{Z|cs}}: {{W+|cs|jařmo}} {{nt}} * {{Z|da}}: {{W+|da|åg}} * {{Z|eo}}: {{W+|eo|jugo}} * {{Z|et}}: {{W+|et|ike}} * {{Z|fa}}: {{W+|fa|یوغ}}, {{W+|fa|یوغ}} * {{Z|fi}}: {{W+|fi|ies}} * {{Z|fr}}: {{W+|fr|joug}} {{n}} * {{Z|ang}}: {{W-|ang|geoc}} * {{Z|en}}: {{W+|en|yoke}} * {{Z|it}}: {{W+|it|giogo}} {{n}} * {{Z|ca}}: {{W+|ca|jou}} {{nt}} * {{la}} [[iugum]] {{n}} * {{Z|hu}}: {{W+|hu|iga}}, {{W+|hu|járom}} * {{Z|sh}}: {{W+|sh|igo}} {{nt}}, {{W+|sh|jaram}} {{n}} * {{Z|sk}}: {{W-|sk|jarmo}} {{nt}} * {{Z|es}}: {{W+|es|yugo}} {{n}} * {{Z|sv}}: {{W+|sv|ok}} {{nt}} * {{Z|tr}}: {{W+|tr|boyunduruk}} {{werger-bin}} 7bdelycuixqpel90i4xbum7oiral7yl 6347295 6347294 2026-08-30T23:40:52Z Wikihez 7344 /* Etîmolojî */ 6347295 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Zugochsen.jpg|thumb|du gayên bi nîr]] {{navdêr|ku|z=n}} # [[dar|Dar]]ê ku du [[ga]] û [[gamêş]] pê tên [[zeft]]kirin dema [[cot]] pê tê kirin yan [[erebe]] pê tê [[kêşan]]. #: {{hevmane|ku|yûx|cûx|nîr}} # {{f|ku|mecazî}} [[zilm]], [[zordestî]], [[stem]], [[bindestî]], [[koletî]] ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|نیر}} ==== Têkildar ==== * {{g|ku|basole}} ==== Etîmolojî ==== {{ji?|ku}} ==== Bide ber ==== {{kol3|ku |bîr |çîr |dîr |gîr |hîr |jîr |kîr |lîr |mîr |pîr |sîr |şîr |tîr |zîr }} ==== Herwiha binêre ==== {{kol3|ku |nar |nêr |nor |nûr }} ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|zgjedhë}} {{mê}} * {{Z|de}}: {{W+|de|Joch}} {{nt}} * {{Z|cs}}: {{W+|cs|jařmo}} {{nt}} * {{Z|da}}: {{W+|da|åg}} * {{Z|eo}}: {{W+|eo|jugo}} * {{Z|et}}: {{W+|et|ike}} * {{Z|fa}}: {{W+|fa|یوغ}}, {{W+|fa|یوغ}} * {{Z|fi}}: {{W+|fi|ies}} * {{Z|fr}}: {{W+|fr|joug}} {{n}} * {{Z|ang}}: {{W-|ang|geoc}} * {{Z|en}}: {{W+|en|yoke}} * {{Z|it}}: {{W+|it|giogo}} {{n}} * {{Z|ca}}: {{W+|ca|jou}} {{nt}} * {{la}} [[iugum]] {{n}} * {{Z|hu}}: {{W+|hu|iga}}, {{W+|hu|járom}} * {{Z|sh}}: {{W+|sh|igo}} {{nt}}, {{W+|sh|jaram}} {{n}} * {{Z|sk}}: {{W-|sk|jarmo}} {{nt}} * {{Z|es}}: {{W+|es|yugo}} {{n}} * {{Z|sv}}: {{W+|sv|ok}} {{nt}} * {{Z|tr}}: {{W+|tr|boyunduruk}} {{werger-bin}} ts0avg7cs2c3lzhuxl8qamnk45ijmlb 6347316 6347295 2026-08-31T01:12:14Z Balyozbot 7867 Bot: Paqijiyên kozmetîk (Lînk paqij kir.) 6347316 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === [[Wêne:Zugochsen.jpg|thumb|du gayên bi nîr]] {{navdêr|ku|z=n}} # [[dar|Darê]] ku du [[ga]] û [[gamêş]] pê tên [[zeft]]kirin dema [[cot]] pê tê kirin yan [[erebe]] pê tê [[kêşan]]. #: {{hevmane|ku|yûx|cûx|nîr}} # {{f|ku|mecazî}} [[zilm]], [[zordestî]], [[stem]], [[bindestî]], [[koletî]] ==== Tewandin ==== {{ku-tewîn-nav/nû|nêr}} ==== Bi alfabeyên din ==== * {{ku-ar|نیر}} ==== Têkildar ==== * {{g|ku|basole}} ==== Etîmolojî ==== {{ji?|ku}} ==== Bide ber ==== {{kol3|ku |bîr |çîr |dîr |gîr |hîr |jîr |kîr |lîr |mîr |pîr |sîr |şîr |tîr |zîr }} ==== Herwiha binêre ==== {{kol3|ku |nar |nêr |nor |nûr }} ==== Werger ==== {{werger-ser}} * {{Z|sq}}: {{W+|sq|zgjedhë}} {{mê}} * {{Z|de}}: {{W+|de|Joch}} {{nt}} * {{Z|cs}}: {{W+|cs|jařmo}} {{nt}} * {{Z|da}}: {{W+|da|åg}} * {{Z|eo}}: {{W+|eo|jugo}} * {{Z|et}}: {{W+|et|ike}} * {{Z|fa}}: {{W+|fa|یوغ}}, {{W+|fa|یوغ}} * {{Z|fi}}: {{W+|fi|ies}} * {{Z|fr}}: {{W+|fr|joug}} {{n}} * {{Z|ang}}: {{W-|ang|geoc}} * {{Z|en}}: {{W+|en|yoke}} * {{Z|it}}: {{W+|it|giogo}} {{n}} * {{Z|ca}}: {{W+|ca|jou}} {{nt}} * {{la}} [[iugum]] {{n}} * {{Z|hu}}: {{W+|hu|iga}}, {{W+|hu|járom}} * {{Z|sh}}: {{W+|sh|igo}} {{nt}}, {{W+|sh|jaram}} {{n}} * {{Z|sk}}: {{W-|sk|jarmo}} {{nt}} * {{Z|es}}: {{W+|es|yugo}} {{n}} * {{Z|sv}}: {{W+|sv|ok}} {{nt}} * {{Z|tr}}: {{W+|tr|boyunduruk}} {{werger-bin}} rtdnqr36ptjp5u4ukjvdk3fqnldwirv un helvası 0 361437 6347202 6208907 2026-08-30T16:26:18Z Nenas nepênî 14450 6347202 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # [[poxîn]] # [[Helawîk]] 9ms3f6n5pdfpf6uph21d79u6b4v8s3f 6347204 6347202 2026-08-30T16:38:12Z Wikihez 7344 ([[m:Special:MyLanguage/User:Jon Harald Søby/diffedit|diffedit]]) 6347204 wikitext text/x-wiki == {{ziman|tr}} == === Navdêr === {{navdêr|tr}} # {{e|tr|şîranî}} [[helawîk]], [[poxîn]] lj2hcl1z9cy6b1vgajxxsy8w1yyi5m8 xweşbext 0 380815 6347329 6255538 2026-08-31T10:07:44Z Wikihez 7344 /* Kurmancî */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347329 wikitext text/x-wiki == {{ziman|ku}} == === Formên alternatîv === * [[xoşbext]] === Etîmolojî === Ji {{qf|ku|xweş|bext}}. === Bilêvkirin === * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # [[bextyar]], [[bextewer]], [[bişans]], [[bitalih]], [[bisiûd]], [[bextfireh]] ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W+|tr|şanslı}} {{werger-bin}} === Rengdêr === {{rengdêr|ku}} # [[bextyar]], [[bextewer]], [[bişans]], [[bitalih]], [[bisiûd]], [[bextfireh]] #* {{jêder-kovar|ku|jêgirtin=M. Clement Huartê1 pisporê ziman û kulturên rojhilata nêzîk, ber bi dawiya sedsala 19an, bi tesadufeke '''xweşbext''', di nav destnivîsareke şi’ra farsî ya arşîva xwe de, bi ser rûpelekê ve dibe, ku tê de mustensixê destnivîsarê, bi usûla salnameyan an kronîkan, ji dawiya sedsala 17an heta ber bi dawiya sedsala 18an, bi rengekî kronolojîk, hejmareke qewimînên tarîxî yên li herêma Badînan û li derdorên wê, anku bi giştî yên bakurê Mezopotamyayê, rêz dike|kovar=The Journal of Mesopotamian Studies|sernav=Kronikek ji Sedsala 18an li ser Tarîxa Badînan û Mezopotamyaya Bakurî|nivîskar=Ergin Öpengin|url=https://dergipark.org.tr/tr/download/article-file/450470|cîld=3|hejmar=1|sal=2018|r=45}} ==== Werger ==== {{werger-ser}} {{werger-bin}} 65mk16ahmbxfvg8vuzyxpujtxp5ls6s Bikarhêner:Wikihez/common.js 2 873671 6347248 6342566 2026-08-30T20:04:56Z Wikihez 7344 6347248 javascript text/javascript /*---------Gadget-morebits.js------------- [[Bikarhêner:Wikihez/skrîpt/Gadget/Gadget-morebits.js]] [[Bikarhêner:Wikihez/skrîpt/Gadget/Gadget-morebits.css]]*/ mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/skrîpt/Gadget/Gadget-morebits.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/Gadget/Gadget-morebits.js&action=raw&ctype=text/javascript'); importScript( 'Bikarhêner:Wikihez/skrîpt/js/Gadget-citoid-helper.js' ); // Backlink: [[Bikarhêner:Wikihez/skrîpt/js/Gadget-citoid-helper.js]] mw.loader.load('//en.wikipedia.org/w/index.php?title=User:Joeytje50/JWB.js/load.js&action=raw&ctype=text/javascript'); /*---------Gadget-DefSideBoxes.js------------- [[Bikarhêner:Wikihez/Gadget-DefSideBoxes.js]] [[Bikarhêner:Wikihez/Gadget-DefSideBoxes.css]] */ mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/Gadget-DefSideBoxes.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-DefSideBoxes.js&action=raw&ctype=text/javascript'); ( function () { 'use strict'; if ( [ 'Recentchanges', 'Watchlist' ].indexOf( mw.config.get( 'wgCanonicalSpecialPageName' ) ) === -1 ) { return; } var style = document.createElement( 'style' ); style.textContent = '.mw-rollback-link { display: none !important; }'; document.head.appendChild( style ); }() ); //[[Bikarhêner:Wikihez/skrîpt/js/templateParamRenamer.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/templateParamRenamer.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/quicklinks.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/quicklinks.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/citeKurdifier.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/citeKurdifier.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-defaultVisibilityToggles.js&action=raw&ctype=text/javascript'); /*---------QQ.js------------- [[Bikarhêner:Wikihez/Gadget-QQ.js]] [[Bikarhêner:Wikihez/Gadget-QQ.css]] mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/Gadget-QQ.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-QQ.js&action=raw&ctype=text/javascript'); */ /*---------add-examples.js------------- [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.js]] [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.css]]*/ mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/Gadget-wikt.add-examples.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-wikt.add-examples.js&action=raw&ctype=text/javascript'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/loader.js&action=raw&ctype=text/javascript') importScript( 'Bikarhêner:Wikihez/skrîpt/js/copyTitle.js' ); // Backlink: [[Bikarhêner:Wikihez/skrîpt/js/copyTitle.js]] // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/addAutoCat.js&action=raw&ctype=text/javascript'); //importScript( 'Bikarhêner:Wikihez/newentrywiz.js' ); // Backlink: [[Bikarhêner:Wikihez/newentrywiz.js]] //[[Bikarhêner:Wikihez/CreateTranslation.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/CreateTranslation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/wergerîne.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/wergerîne.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/getinflections.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/getinflections.js&action=raw&ctype=text/javascript'); //[[:w:Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js]] mw.loader.load('//ku.wikipedia.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/OngletPurge.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/templateScript2.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/templateScript2.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/şablon-lêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/şablon-lêke.js&action=raw&ctype=text/javascript'); mw.loader.load('https://en.wikipedia.org/w/index.php?title=User:BrandonXLF/TodoList.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/test.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/test.js&action=raw&ctype=text/javascript'); //================================================================================================================================ /*---------start.js------------- [[Bikarhêner:Wikihez/Gadget-start.js]] [[Bikarhêner:Wikihez/Gadget-start.css]] mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/Gadget-start.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-start.js&action=raw&ctype=text/javascript'); */ //importScript( 'Bikarhêner:Wikihez/Gadget-linkify.js' ); // Backlink: [[Bikarhêner:Wikihez/Gadget-linkify.js]] //[[Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/Gadget-catfix.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/editor.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/UpdateLanguageNameAndCode.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/skrîpt/js/TranslationAdder-Data.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/LanguageUtils.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/LanguageUtils.js&action=raw&ctype=text/javascript'); /*---------aWa.js------------- [[Bikarhêner:Wikihez/Gadget-aWa.js]] [[Bikarhêner:Wikihez/Gadget-aWa.css]] mw.loader.load(mw.util.wikiScript() + '?title=Bikarhêner:Wikihez/Gadget-aWa.css&action=raw&ctype=text/css', 'text/css'); mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-aWa.js&action=raw&ctype=text/javascript'); */ // This array of dependencies comes from [[MediaWiki:Gadgets-definition]]. // If the list of dependencies changes, copy the text after dependencies= // for TranslationAdder and run console.log(JSON.stringify("paste dependencies here".split(/, ?/))) // in your browser's JavaScript console. Put the resulting array as the first argument to mw.loader.using. //[[User:Wikihez/skrîpt/js/TranslationAdder.js]] //mw.loader.using(["ext.gadget.LegacyScriptsNewNode","mediawiki.cookie","mediawiki.util"], //function() { // importScript('User:Wikihez/skrîpt/js/TranslationAdder.js'); //}); /* // [[:w:en:MediaWiki:Gadget-edittop.js]] mw.loader.load('//en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-edittop.js&action=raw&ctype=text/javascript'); // [[Bikarhêner:Wikihez/addAutoCat.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/addAutoCat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Balyozbot/Gadget-CommonWikt.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Balyozbot/Gadget-CommonWikt.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/hw-ceke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/hw-ceke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/sort-langheaders.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/sort-langheaders.js&action=raw&ctype=text/javascript'); //[[:en:User:Conrad.Irwin/Api.js]] mw.loader.load('//en.wiktionary.org/w/index.php?title=User:Conrad.Irwin/Api.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/etîket-çêke.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/etîket-çêke.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/tagger.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/tagger.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-CatMaker.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-CatMaker.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/VisibilityToggles.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/VisibilityToggles.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Gadget-WiktAccFormCreation.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/XMLize.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/XMLize.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/RhymesAdder.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/RhymesAdder.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/Editor.js]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/Editor.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/FilterTranslations.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/FilterTranslations.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/custom.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/custom.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/reformat.js]] //mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/reformat.js&action=raw&ctype=text/javascript'); //[[Bikarhêner:Wikihez/translateWiki.js]] ji aliyê [[Bikarhêner:Guherto]], [[Taybet:PermanentLink/4854098#Translatewiki.net]] mw.loader.load('//ku.wiktionary.org/w/index.php?title=Bikarhêner:Wikihez/translateWiki.js&action=raw&ctype=text/javascript'); // Various fixes for the trees generated by [[Module:family tree]]. $(function () { // Show the top toggle. $('.familytree-toptoggle').css('display', ''); // Initialize the text of the toggles. $('.familytree').get().forEach(function (tree) { var isCollapsed = tree.classList.contains('mw-collapsed'); var toggles = $(tree).find('.familytree-toggle'); if (toggles[0]) { var customToggleClass = Array.prototype.filter.call(toggles[0].classList, function (className) { return className.indexOf('mw-customtoggle-familytree') === 0; })[0]; if (customToggleClass) { var toggledElement = $('#' + customToggleClass.replace('mw-customtoggle', 'mw-customcollapsible')); if (toggledElement) { toggles.html(toggledElement.data(isCollapsed ? 'expandtext' : 'collapsetext')); } } } }); // Change the text in the custom toggles generated by [[Module:family tree]] // when they are clicked. $('.mw-collapsible').on('beforeExpand.mw-collapsible beforeCollapse.mw-collapsible', function (event) { if (this.id.indexOf('mw-customcollapsible-familytree') === 0) { var toggle = $('.' + this.id.replace('mw-customcollapsible', 'mw-customtoggle')); if (event.type === 'beforeExpand') { toggle.html(this.dataset.collapsetext); } else { // beforeCollapse toggle.html(this.dataset.expandtext); } event.stopPropagation(); } }); }); */ 5f6valj42q62ssmlpu23s4cria6qgqy Gotûbêja MediaWiki:Gadget-wikt.add-examples.js 9 1275535 6347301 5896041 2026-08-31T00:29:08Z Wikihez 7344 [[MediaWiki:Gadget-aWa.js/belgekirin|aWa]]: Arşîvkirina nîqaşê ji rûpela [[Wîkîferheng:Xebat]] 6347301 wikitext text/x-wiki == Color == Silav @[[Bikarhêner:Ghybu|Ghybu]]. Rengê lînka "Nimûneyeke bikaranînê lê zêde bike" bikim: {{code|js|$button.css("color", "#777777");}} Wekî li vir [[Bikarhêner:Balyozxane/test.js#L-214]] (wekî [[:en:Template:maintenance line]])? Ji ber ku dema rûpelê de çend heb ji wan lînkan hebin, xwendina maneya kelîmeyê pir zor dibe. [[Bikarhêner:Balyozxane|Balyozxane]] ([[Gotûbêja bikarhêner:Balyozxane|gotûbêj]]) 16:28, 20 kanûna pêşîn 2023 (UTC) :Mînak {{q|tr|sistem}} -- [[Bikarhêner:Balyozxane|Balyozxane]] ([[Gotûbêja bikarhêner:Balyozxane|gotûbêj]]) 16:34, 20 kanûna pêşîn 2023 (UTC) == MediaWiki:Gadget-wikt.add-examples.js == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6347299#MediaWiki:Gadget-wikt.add-examples.js}} Min ev amûr hinek rojane kir feqat çend problem hene berî ku bar bikin. Tiştên ku min guhart: # Êdî li sayfeyên bi {{ş|maneid}} jî dixebite, # Cihê di wîkîtekstê de yê ku jêgirtin were îlawekirin baştir bû, # [[Mediawiki:Gadget-citoid-helper.js|citoid helper]] zêde kir ji bo ku bi hêsanî çavkanî bi riya doi, isbn an urlyê werin tijîkirin. * [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.css]] --> [[MediaWiki:Gadget-wikt.add-examples.css]] * [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.js]] --> [[MediaWiki:Gadget-wikt.add-examples.js]] - --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:50, 19 tîrmeh 2026 (UTC) :Min "wikt." qismên cache kirinê ya wîkiya fransî bi [[MediaWiki:Gadget-StorageUtils.js]] guhartiye. loma ji bîr nekin wê amûrê li [[MediaWiki:Gadgets-definition]] zêde bikin. û navê amûrê jî biguhêrînin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:15, 23 tîrmeh 2026 (UTC) ::Berê li ser WF:ceribandin dixebitî. niha naxebite. Divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:10, 7 tebax 2026 (UTC) :::Muhîm e û zû were rastkirin feqat piştî îro ez çend rojan misaîd nebim: :::* Li şûna Navdêr 2, jêgirtin çû Navdêr 1 [https://ku.wiktionary.org/w/index.php?title=palas&diff=prev&oldid=6337440] :::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:01, 19 tebax 2026 (UTC) ::::{{çêbû}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:28, 31 tebax 2026 (UTC) {{arşîv-bin}} jn1qgthtsmzx4p5mpx0b7atihprgsby Wîkîferheng:Dîwan/2026 4 1327120 6347268 6342926 2026-08-30T21:39:39Z Wikihez 7344 /* Heqên Interface admîntiyê */ beşeke nû 6347268 wikitext text/x-wiki <noinclude>{{Dîwan/arşîv-ser|2026}}</noinclude> {{clear}} == Daxwazên standardkirinê == https://ku.wiktionary.org/wiki/W%C3%AEk%C3%AEferheng:Daxwaz%C3%AAn_standardkirin%C3%AA, Gelo di vê malperê de peyvên hatîye standart kirin; ji malperê rakin? Zêde tehlîhev e. @[[Bikarhêner:Bikarhêner|Bikarhêner]]@[[Bikarhêner:Guherto|Guherto]] [[Bikarhêner:Rewiye tine|Rewiye tine]] ([[Gotûbêja bikarhêner:Rewiye tine|gotûbêj]]) 10:03, 8 kanûna paşîn 2026 (UTC) :@[[Bikarhêner:Rewiye tine|Rewiye tine]] [[Taybet:Tercîh#mw-prefsection-gadgets]] li vir amûra [[MediaWiki:Gadget-aWa.js/belgekirin|awa]] aktîv bike û pê re dikarî gotûbêjan arşîv bikî. Li sayfa [[WF:DS]] li kêleka her sernavê gotûbêjê <nowiki>[arşîv bike]</nowiki> derdikeve, pê lê bike û ew ê arşîv bike. Eger nikarî tu tenê şablona {{ş|ds-kirî}} îlawe bike, ez ê dûre arşîv bikim. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:35, 5 tîrmeh 2026 (UTC) == Standartkirin == Sala borî, min pêşnîyazek kiribû. Halî hazir piştî daxwaza standarkirinê em du heftî disekinin, eger kesek fikrek dîyar neke. Raste rast peyv li gor ferhenga standart a mezopotamyayê tê standart kirin. Ji xwe sazîyek vê karî dike çima em vê barî dikin stuyê xwe. Mesela ez çaxe di wîkîferhengê de peyvek digêrim; standart a peyvê jî li cem xwe kontrol dikim. Eger destûr hebe bi germî dikarim wê malperê standart bikim. Benda bûna du heftîyan gelo ne zehmet e? Duyemîn pêşnîyaza min nîşandana standarta peyvê di malpera de ye. Kesek dema malperan binêre, divê li jora malperan bibîne ku ev peyv standart e. Ev jî hîzmet e. Çimkî nivîskar, wergêr, edîtor, rojnemavan hez dikin bi peyvê standart binivîsin. https://ku.wiktionary.org/wiki/k%C3%AAf li vir wekî mînak min daye nîşan. Lê îfade eger wisa be: Standarda Rastnivîsîna Ferhenga Kurdî a Weqfa Mezopotamyayê kêf (r. 253) e yê çetir be. Çimkî îfadeya berê de peyva kurdî-tirkî derbas dibe û di mejîyê mirov de tevlihevî çêdibe.@[[Bikarhêner:Bikarhêner|Bikarhêner]]@[[Bikarhêner:Guherto|Guherto]] [[Bikarhêner:Rewiye tine|Rewiye tine]] ([[Gotûbêja bikarhêner:Rewiye tine|gotûbêj]]) 10:25, 8 kanûna paşîn 2026 (UTC) :Merheba. Hevalno dîyar e karê standarkirinê li wîkîferhengê rawestîya ye. Min sê peyv ji bo standartkirinê qeyd kir. Kes li ser şîrove nenivîsî. Mehek jî li ser derbas bû. Aniha ez dikarim van rupelan biguherim. Li gor qaîdeya hatine danîn wisa ye. Daxwaza min heta niha jî ew e kelîmeyên di ferhenga standartkirinê de heyî divê em bikaribin rasterast li vir jî bikin standart. An jî demê kurttir bikin. Li weqfa mezapotamyayê 20 mirov digêhin hev li ser peyvekî seetan nîqaş dikin. Ma hewceyê em jî li vir nîqaş bikin? Tevlî vê jî ji xwe kes li ser vê mijare nasekîne van dema. Xeynî vê pêşnîyaza min nîşandana standarta peyvê di malpera de hebû. Li ser malperê 'Standarda Rastnivîsîna Ferhenga Kurdî a Weqfa Mezopotamyayê kêf (r.253) e' Tiştek mîna wî hebe yê gelek kêrî her cure nivîskarê me were. Çimkî hin nivîskarên me hez dike bi kelîmeyên standart binivîse. Di malperê de bila vê hêsanî fam bike çêtir e. @[[Bikarhêner:Bikarhêner|Bikarhêner]]@[[Bikarhêner:Ghybu|Ghybu]] [[Bikarhêner:Rewiye tine|Rewiye tine]] ([[Gotûbêja bikarhêner:Rewiye tine|gotûbêj]]) 18:35, 17 sibat 2026 (UTC) ::Merheba @[[Bikarhêner:Rewiye tine|Rewiye tine]]. Ev format pir xirab dibe. Tu dikarî li beşa Çavkaniyê binivîsî bi şablona {{ş|kitêb}} binivîsî çêtir e û tê eynî maneyê. Lê her kes standarda Weqfa Mezopotamyayê qebûl nakin û ez jî şibhê dikim ku ev websîte bi awayekî kolektîv tê çêkirin an na. Loma em bi ya kitêba rastnivisînê çêkin û eger îtîraz tinebe, şablona {{ş|ds-kirî}} li gotûbêja [[WF:DS]] binivîse, dûre li gotûbêjê arşîv bike, ne hewce ye li hêviya kesên din bisekinî. Eger itirazek hebe, ê ku dixwaze dûre dîsa şablona ds zêde bike. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:30, 5 tîrmeh 2026 (UTC) :::[https://berwarnews.com/ferhenga-rastnivisine-qonaxeke-giring-a-standardkirina-kurmanci-ye/ Roportaja Mikail Bülbül] li ser proseya standardkirinê. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:57, 9 tîrmeh 2026 (UTC) ::::Min nû dît an jî nû hatiye zêdekirin lê meqaleyek bi navê [https://www.ferhengkurdi.com/?q=iltihap&modal=lijne lijneya edîtorîyê] nivîsandine [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:40, 22 tîrmeh 2026 (UTC) == <span lang="en" dir="ltr">Annual review of the Universal Code of Conduct and Enforcement Guidelines</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> I am writing to you to let you know the annual review period for the Universal Code of Conduct and Enforcement Guidelines is open now. You can make suggestions for changes through 9 February 2026. This is the first step of several to be taken for the annual review. [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|Read more information and find a conversation to join on the UCoC page on Meta]]. The [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Universal Code of Conduct Coordinating Committee]] (U4C) is a global group dedicated to providing an equitable and consistent implementation of the UCoC. This annual review was planned and implemented by the U4C. For more information and the responsibilities of the U4C, [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|you may review the U4C Charter]]. Please share this information with other members in your community wherever else might be appropriate. -- In cooperation with the U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]])<section end="announcement-content" /> </div> 21:02, 19 kanûna paşîn 2026 (UTC) <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == Request for comment (global AI policy) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies for writing in English. {{int:Please-translate}} A [[:m:Requests for comment/Artificial intelligence policy|request for comment]] is currently being held to decide on a global AI policy. {{int:Feedback-thanks-title}} [[Bikarhêner:MediaWiki message delivery|MediaWiki message delivery]] ([[Gotûbêja bikarhêner:MediaWiki message delivery|gotûbêj]]) 00:58, 26 nîsan 2026 (UTC) </bdi> <!-- Message sent by User:Codename Noreste@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30424282 --> == Guharto == : <small>→ Ji rûpela ''[//ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:berf%C3%AEtik&oldid=6233338 Gotûbêj:berfîtik]'' hatiye girtin.</small> Silav {{r|Ghybu}} ma hewce ye em guhartoyan jî kategorîze bikin? Li vê [[ژیشک]] binere, tije guhartoyên wê hene, ku em ji gişan re guhandar binivîsin dê 10 navên heman hebin di nav wê kategorîyê de. Tu çi difikirî? [[Bikarhêner:Keyomerd|Keyomerd]] ([[Gotûbêja bikarhêner:Keyomerd|gotûbêj]]) 09:40, 26 nîsan 2026 (UTC) :{{silav|Keyomerd}}. Erê, problem çî ye? {{=)}} Ew jî tên bikaranîn... Dema ku peyvek tê çêkirin hewce ye ku em hemû agahiyên wan binivîsin: bilêvkirin, bikaranîn, mînak, terîm, herêm, tewandin, etîmolojî... :Bi min peyvên ku wekî ''guherto'' hatine nivîsandin bi nivîsa {{w|Italic type|îtalîk|ziman=en}} (xwahr) di nav kategoriyan de werin nişan kirin (ji bo cudakirinê). {{ping|Ferhengvan|Bikarhêner}} [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:40, 30 nîsan 2026 (UTC) ::Yên '''''nestandard''''' di kategorîyan de biferq werin nîşandan baştir e. Qene em karibin wan ji yên stadard ferq bikin. @[[Bikarhêner:Ghybu|Ghybu]] Xêra xwe hûn sîstemeke wisa çêkin. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 14:36, 1 gulan 2026 (UTC) :::Merheba @[[Bikarhêner:Keyomerd|Keyomerd]] û @[[Bikarhêner:Bikarhêner|Bikarhêner]] ev xisûsiyet jixwe di şablonên rêzimanê de heye, wextê {{param|formaalt|1}} dinivîsin, made dikeve Kategoriya [[:Kategorî:Formên alternatîv bi kurmancî]] li gorî koda zimanî jî zimanên din tê çêkirin. Hemû madeyên kurmancî bi alfabeya erebî dikevin vê kategoriyê lê nizanim ev tiştekî rast e Yan xelet e, ji bo nîşandanê min çêkiribû lê min hîn wext nedît ku nîqaşek li ser çêkim. Qaîdeyên bikaranîna vê parametreyê di wîkiya îngilîzî de jî tam ne belî ye. Du gotûbêj [https://en.wiktionary.org/wiki/Wiktionary:Requests_for_moves,_mergers_and_splits#Category:Alternative_forms_by_language] [https://en.wiktionary.org/wiki/Wiktionary:Beer_parlour/2024/June#Decluttering_the_altform_mess] çêkirine lê ji bo îngilîzî ev parametre nehatiye bikaranîn. Min ji bo nîşandanê niha [https://ku.wiktionary.org/w/index.php?title=bax%C3%A7%C3%AA_zarokan&diff=prev&oldid=6241372] ceriband lê bi min xelet e. Em çawa bikin? Kengî vê parametreyê bi kar bînin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:29, 8 tîrmeh 2026 (UTC) ::::@[[Bikarhêner:Kurdanparez|Kurdanparez]] Tu çi difikirî? Ji bo zazakî [https://ku.wiktionary.org/w/index.php?title=a_c%C4%B1_geyrayene&oldid=6241396 wisa] bikin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:55, 8 tîrmeh 2026 (UTC) :::::Kategorîyekê cuda baş dibe. Wextê ku ez li kategorîya "lekêren bi zazakî" dinêrim, ez hem formê bi şikilê Johnsonê û formê standardê dibînim. Zaten wexte ku ez dikevim ê Johnsonê, min dibe formê standardê. Kategorîyekê cuda, bi taybetî ji bo nivîsandinên alternatîf, baş dibe. :::::Lê em bîr nekin ku wextê ku em bo formên alternatîf yên devokî qal dikin, belkî adil neye ku em ev bişînin derekê din yê ku însan ewqas nabînin. [[Bikarhêner:Kurdanparez|Kurdanparez]] ([[Gotûbêja bikarhêner:Kurdanparez|gotûbêj]]) 22:03, 8 tîrmeh 2026 (UTC) ::::::@[[Bikarhêner:Kurdanparez|Kurdanparez]] Gelo min rast fêm kir? Tu dibêjî formên {{q|ku|kîvroşk}} bi dîqet werin guhartokirin lê bi yên bi alfabeya Jacobsonê hemû bikin {{param|formaalt|1}}? Formên Jacobsonê dê bikevin Kategoriya [[:Kategorî:Lêker bi zazakî|Lêker bi zazakî]] û [[:Kategorî:Lema bi zazakî|Lema bi zazakî]] yan na? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:55, 8 tîrmeh 2026 (UTC) :::::::Bi min naxwaze di wan kategoriyan de bikeve. Wek tu dibînî dûplîkat pir hene. Bi min çareya baştir yên Johnsonê di katehgorîyekê din bikevin (bila format li rûpelan neyin guherandin, bi tenê kategorî) [[Bikarhêner:Kurdanparez|Kurdanparez]] ([[Gotûbêja bikarhêner:Kurdanparez|gotûbêj]]) 00:37, 9 tîrmeh 2026 (UTC) == Peyvên soranî bi latînî ([[:Kategorî:Soranî]]) == Silav, di nav vê kategoriyê (''[[:Kategorî:Soranî]]'') de pirr peyv tenê bi alfabeya latînî hatine nivîsandin. Divê ew mutleq jî bi alfabeya erebî werin transkrîbe kirin ji ber ku soranî bi alfabeya erebî tê nivîsand... Bikarênerên ku soranî dizanin dikarin wan sererast bikin? Mînakên guhertinan: [//ku.wiktionary.org/w/index.php?title=zor%C3%AEne&curid=6584&diff=6233355&oldid=5859303], [//ku.wiktionary.org/w/index.php?title=s%C3%AAw&diff=6233097&oldid=6233003], [//ku.wiktionary.org/w/index.php?title=sewz&diff=6233313&oldid=6069107], ... Spas! [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 01:16, 2 gulan 2026 (UTC) == <span lang="en" dir="ltr">Vote now in the 2026 U4C election</span> == <div lang="en" dir="ltr"> <section begin="announcement-content" /> Eligible voters are asked to participate in the 2026 [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee|Universal Code of Conduct Coordinating Committee]] election. More information–including an eligibility check, voting process information, candidate information, and a link to the vote–are available on Meta at the [[m:Special:MyLanguage/Universal_Code_of_Conduct/Coordinating_Committee/Election/2026|2026 Election information page]]. The vote closes on 2 June 2026 at [https://zonestamp.toolforge.org/1780358400 00:00 UTC]. Please vote if your account is eligible. Results will be available by 14 June 2026. -- In cooperation with the U4C,<section end="announcement-content" /> </div> [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|talk]]) 17:15, 27 gulan 2026 (UTC) <!-- Message sent by User:Keegan (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == RFC about AI-generated content in Wikimedia Commons == <bdi lang="en" dir="ltr">Apologies for writing in English, please help translate this message to your language. You are invited to participate in a [[c:Commons:Requests for comment/Policy update for AI content|request for comment on Wikimedia Commons about a policy update for AI content]]. This may affect files that are uploaded to Wikimedia Commons for use on this project. Thank you. [[m:User:Codename Noreste|Codename Noreste]] ([[m:User talk:Codename Noreste|gotûbêj]])</bdi> 17:12, 23 hezîran 2026 (UTC) <!-- Message sent by User:Codename Noreste@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == <span lang="en" dir="ltr">Deployment of Legal and Safety Contacts Link in the Footer of Your Wiki</span> == <div lang="en" dir="ltr"> <section begin="Message"/> '''Legal & Safety Contacts''' Hello community, the Wikimedia Foundation has provided a [[wmf:Special:MyLanguage/Legal:Wikimedia Foundation Legal and Safety Contact Information|single legal and safety contact page]], to be linked in the footer of your wiki, to ensure access to accurate legal information. This is a regulatory requirement. We have already rolled out links to English, German, Italian, Spanish and other wikis and we will deploy to your wiki soon. [[m:Special:MyLanguage/Wikimedia_Foundation_Legal_and_Safety_Contacts_FAQ|Please read more on the project page]] and leave any comments in this thread or on the [[m:Special:MyLanguage/Talk:Wikimedia Foundation Legal and Safety Contacts FAQ|talk page]]. <section end="Message"/> </div> -- [[User:Sannita (WMF)|User:Sannita (WMF)]] ([[User talk:Sannita (WMF)|talk]]) 13:31, 25 hezîran 2026 (UTC) <!-- Message sent by User:Sannita (WMF)@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=User:Sannita_(WMF)/Mass_sending_test&oldid=30731267 --> == Jêbirina ferhenga Sadallah == Merheba @[[Bikarhêner:Guherto|Guherto]] Îmkan heye lîsteyeke wisa çêkî ku hemû sayfeyên Cyrusbot çêkir yên ku tê de tenê tercimeyeke îngilîzî heye û ev tercime jî hatibe jêbirin? Nimûne ''[[derdzanî]], [[êşzanî]]'' tenê tercimeya [[pestology]] heye ew jî ji ber heqê telîfê hatiye jêbirin. Nimûneyeke din ''zêrrgeh'', ''zêrrkar'' [[goldsmith]] hatiye jêbirin zêr wekî zêrr hatiye guhartin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:48, 26 hezîran 2026 (UTC) :Temam @[[Bikarhêner:Wikihez|Wikihez]], lê vê heyvê ez nikarim, heyva were ez ê li vê meseleyê vegerim înşellah. [[Bikarhêner:Guherto|Guherto]] ([[Gotûbêja bikarhêner:Guherto|gotûbêj]]) 22:51, 2 tebax 2026 (UTC) ::Merheba @[[Bikarhêner:Wikihez|Wikihez]], min lîste çêkir. [[WF:Gotarên ku bên jêbirin/Ferhenga Salah Sadallah/ku]]. Di vê lîstê de tenê rûpelên ko însan dest nedanê de hene. [[Bikarhêner:Guherto|Guherto]] ([[Gotûbêja bikarhêner:Guherto|gotûbêj]]) 23:05, 27 tebax 2026 (UTC) == Beşa Tewandin bo kurmancî == Bi ya min şablona {{ş|ku-tewîn-nav}} û ya fiîlê em bixin beşa Tewandinê (wekî [[şodir|zazakî]]. Bi vî awayî hem ji aliyê şiklî ve hem jî ji aliyê bikaranînê ve xweştir xuya bike. Eger di qismê Tewandinê de be, ê ku dixwaze îzah û notên xwe yan jî emilandinên din jî dikare binivîse. Hûn çi dibêjin? @[[Bikarhêner:Ferhengvan|Ferhengvan]], @[[Bikarhêner:Ghybu|Ghybu]], @[[Bikarhêner:Bikarhêner|Bikarhêner]]. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:05, 6 tîrmeh 2026 (UTC) :Belkî em dikarin Formata şiweyan wekî ya behdînî jî têxin nav şablonê. Pir caran şiklê tabloya Tercimeyan ji ber dirêjbûna şablona teqînê jî xirab dibe wekî [[astrofizîk]]. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:08, 6 tîrmeh 2026 (UTC) :Min mijarê te li jorê yê xwe dît, fikirên min jî hene eger baş e. Yê ku te gotiye bi min baş dibe, ji ber ku her rûpel ji vê mîna hev dibe. Em ê rindtir jî ferq li nav devokan binivîsin. [[Bikarhêner:Kurdanparez|Kurdanparez]] ([[Gotûbêja bikarhêner:Kurdanparez|gotûbêj]]) 11:44, 7 tîrmeh 2026 (UTC) ::@[[Bikarhêner:Bikarhêner|Bikarhêner]] fikr? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 08:44, 15 tîrmeh 2026 (UTC) :::Formata ku te teklîf kirîye jî ne xerab e, baş tê xuyan. Feqet bi min halê berê (mewcûd) baştir e. Ji ber ku ev şablon (ku-tewîn-nav) bi piranî kurt in û ji bo her kesî ne mihîm e, lewma li kinarê bi formeke hebe ku karibe were vekirin û girtin baştir e. Lê belê ger şablon dirêjtir bin, em karin wekî ya wîkîya almanî bikin (ew jî wekî teklîfa te ye). -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 09:50, 15 tîrmeh 2026 (UTC) ::::Em tabloya lêkerê jî rakin? 1)Em wekî navdêran bikin, bin beşa Tewandinê 2) Tabloya {{ş|ku-tewîn-reh}} were şûnda tabloya {{ş|ku-tewîn-lk}}: '''[//ku.wiktionary.org/w/index.php?title=gotin&diff=prev&oldid=6323518]''' , '''[//ku.wiktionary.org/w/index.php?title=vexwarin&diff=prev&oldid=6323525]''' 3) Bi şablona {{ş|tewandin}} û bi parametreyên {{param2|niha}} û {{param2|borî}}: '''[//ku.wiktionary.org/w/index.php?title=vexwarin&diff=6323528&oldid=6323525]'''--[[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 10:46, 3 tebax 2026 (UTC) :::::Ez dibêjim em {{ş|ku-tewîn-lk}} bixin bin beşa Tewandinê feqat dema niha û borî tevî formên wan ên negatîv tê de cih bigire, hinek fireh be jî baş e. Dilê min dixwaze yek ji opsiyonên 2 û 3 tevî beşa Tewandinê jî bi kar bînin lê nizanim kîjan hilbijêrin? Herwiha ji bo îsman em dikarin resim zêde bikin ji bo nîşandanê, em ê fiîlan çawa bikin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:10, 3 tebax 2026 (UTC) ::::::Bi min ji bo kesên ku kurmancî dizanin, tabloya tewandinê "piranî" ne hewce ye. Dema ku ez lêkereke nû hu dikim pêşta rehê wê digerim paşê jî devoka wê... Şablonana "ku-tewîn-reh" pirr dirêj nîne: li ser mobîlê jî pirsgirêk nîne: bin beşa "Lêker"ê de tê nivîsandin: lojîk e. Problema beşa Tewandinê va ye: em ê hertim du rûpel serrast bikinê, rupela lêker (beşa "Tewandinê") û rûpela Tewandin:''lêker''. Bila hêmû gotûbêj tenê li ser rûpela Tewandinê were kirin. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 15:06, 3 tebax 2026 (UTC) :::::::Erê em ku-tewîn-lk bi ku-tewîn-reh biguherînin dê baştir bibe. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:30, 4 tebax 2026 (UTC) ::::::::Parametreya {{param2|hêl|çep}} jî hat tevlî tabloyê kirin, bnr. {{q|ku|pêçandin}}. Herwiha niha wekî tabloyên navdêran tên veşartin jî (''Toggle element''), bnr. {{q|ku|xwarin}}. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 13:41, 22 tebax 2026 (UTC) == Reşwî == Silav ji we gî re, Pirsekê min heye. Ez difikirim şablonekê din çê bikim boy devokek kurmancî, yê êla Reşwî. Ew lêkerên xwe hinek cuda ditewînin. Mesela te hem "ez dikim" bêjî yan jî "ez dikime", "em dikinî, em tênî, te em kuştinî" (ne "em dikin") dema xwe yek in lê maneyên xwe ne yek in, "ez bikim" "ez ê bikim" "ez bikime" û dewamên xwe hemû demên xwe yek in lê mane dîsa ne yek in. Eger min çê kir, şûna xwe li ku derê tînim? Ez difikirim li tewandina devokên kurdî yê ku "tabên" xwe hene "kurmancîya rojavayî", "kurmancîya standard" hsw. Lê tewandin ewqes cuda ye dixwaze ku wî şablona tewandina kurdî pir were guherîn. Hûn çi dibêjin? (R: Hûn dewên çi?) [[Bikarhêner:Kurdanparez|Kurdanparez]] ([[Gotûbêja bikarhêner:Kurdanparez|gotûbêj]]) 11:38, 7 tîrmeh 2026 (UTC) :{{silav|Kurdanparez}} Binêre mînaka devoka ''rojhilatî'': [[Modul:ku-tewandin#L-135]] / [[Modul:ku-tewandin#L-138|L138]] / [[Modul:ku-tewandin#L-143|L-143]], .. Di nav modula ''ku-tewandin"-ê de tê çêkirin. [[Gotûbêja modulê:ku-tewandin#Paşgirên lêkeran di kurmanciya rojhilatî de]] [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 13:09, 7 tîrmeh 2026 (UTC) ::PS: Dema niha: [[Modul:ku-tewandin#L-128]]; dema borî: [[Modul:ku-tewandin#L-153]] [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 13:15, 7 tîrmeh 2026 (UTC) :::Merheba @[[Bikarhêner:Ghybu|Ghybu]], Eger mimkin be tu dikarî yên devokî têxî binmodulekê û bila modul load bike, bi vî awayî belkî çêkirina yên nû û famkirina modulê hêsantir be? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 15:09, 7 tîrmeh 2026 (UTC) :::Lê di devokê reşwî de hem dema niha yê statîk heye (Îng: I do -> Ez dikim) û yê progressîf heye (I am doing -> Eîz (nêr) Ez î (mê) dikime, yan jî Ez î dikime/Ez ê dikime). Reşwî ji yê standardê pirtir bo zayend ferq tîne, hem jî li dema pêşî (Ez ê bikim (Nêr) ez a bikim (Mê)). Dema pêşî jî formên cuda hene (Ezêk bikime (I will be doing it) û ez ê/a bikim (I will do it)) :::Ev di modûlê têhel bê? [[Bikarhêner:Kurdanparez|Kurdanparez]] ([[Gotûbêja bikarhêner:Kurdanparez|gotûbêj]]) 22:09, 8 tîrmeh 2026 (UTC) == WF:Xebat == Min sayfeya [[WF:Xebat]] çêkir, xeletiyên ku hûn ferq dikin ji kerema xwe lê zêde bikin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:35, 15 tîrmeh 2026 (UTC) == Modul:quote == @[[Bikarhêner:Ghybu|Ghybu]], @[[Bikarhêner:Bikarhêner|Bikarhêner]], @[[Bikarhêner:Keyomerd|Keyomerd]], @[[Bikarhêner:Ferhengvan|Ferhengvan]] Merheba, ez modula îngilîzî ya jêgirtin û çavkaniyan li gorî şablonên {{ş|jêder}} format dikim û ji bo ku hertişt wekî formata me ya niha be, gelek serê min diêşe. Ez dibêjim bila em dev ji formata niha berdin wekî ya îngilîzî bi kar bînin ji ber ku gelek xisûsiyetên îngilîzî hene ku yekî dikare biemilîne. Hûn ê bibêjin niha ji kû hat bîra tê, min got [[Wîkîferheng:Xebat#MediaWiki:Gadget-start.js|start.js]] nû bikim û min dît otomatîk çavkanî bi riya [[mw:Citoid]]ê bi riya DOI, ISBN û lînk tê çêkirin, min got wiya jî li skrîptê îlawe bikim loma min [[Wîkîferheng:Xebat#Mediawiki:Gadget-citoid-helper.js|Mediawiki:Gadget-citoid-helper.js]] hazir kir lê hin parametreyên Citoidê kêm bûn, min got ka wana rast bikim, min dît formata me ya niha ti standard bi kar nayîne tenê parametreyan bi virgulê li hev dixe. Ez dibêjim formata îngilîzî baştir e, hem ne îtalîk e ku bi hêsanî tên xwendin, hem jî tarîx û çavkanî herî pêşî tên nîşandan ku ji bo peyitandinê bo min muhîm e. Modula îngilîzî de hema bêje her tişt hatiye çêkirin, eger em rûnin tenê yên lazim li şablona çavkaniyên xwe binivîsin ew ê gelek wext bistîne. Eger em modula îngilîzî bi kar bînin, em ê hem karibin şablonên îngilîzî bi hêsanî û rast kopî bikin hem jî kurdîkirina parametreyan gelek hêsan e. Fikir? --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:20, 24 tîrmeh 2026 (UTC) : Ji bo miqayesekirinê bnr. [[:en:Template:quote-book]] / [[Şablon:jêder-kitêb/ceribandin]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:32, 24 tîrmeh 2026 (UTC) ::Bi min bila yê mewcûd jî bimîne, ew jî şiklen xweş û baştir e. Feqet bi min jî yên îngilîzî rehettir in, eger rastkirina yê mewcûd zehmet be, em rasterast wan ji xwe re bînin û tercime bikin. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 09:41, 24 tîrmeh 2026 (UTC) :::Ez êvarê ve dixebitim, min nêzîk kiribû lê min got belkî hûn qane bibin lê xuya ye hûn ê hîn serê min gelek biêşînin {{=D}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:59, 24 tîrmeh 2026 (UTC) ::::@[[Bikarhêner:Bikarhêner|Bikarhêner]] û @[[Bikarhêner:Ghybu|Ghybu]] Eger îtîrazek tinebe, ez ê îtalîk ji jêgirtinê rakim... Jixwe bi riya [jêgirtin] dikare were veşartin û her daim bi * dest pê dike loma bi hêsanî tê fêmkirin û xwendin rihettir dibe. Bnr. [https://ku.wiktionary.org/w/index.php?title=W%C3%AEk%C3%AEferheng:ceribandin/nim%C3%BBne&oldid=6277132#L%C3%AAker_2 ceribandinê] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:13, 24 tîrmeh 2026 (UTC) == Request for comment (the future of Abstract Wikipedia) == <bdi lang="en" dir="ltr" class="mw-content-ltr"> Apologies if this has not yet been translated into your wiki's language. {{int:Please-translate}} You are invited to voice your opinions in a [[:m:Requests for comment/The future of Abstract Wikipedia|request for comment about the future of Abstract Wikipedia]]. {{Int:Feedback-thanks-title}} [[:m:User:Kowal2701|Kowal2701]] ([[:m:User talk:Kowal2701|talk]]) 12:25, 24 tîrmeh 2026 (UTC) </bdi> <!-- Message sent by User:DreamRimmer@metawiki using the list at https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=30513860 --> == ''mê'' yan ''nêr'' li gorî maneyê / ''mê'' yan ''nêr'' (bikaranîn dudil e) == [//ku.wiktionary.org/w/index.php?title=xelat&diff=prev&oldid=6291766]: Mixabin pirr bikarhêner şûnda parametreya <code>z=m/n</code> ('' m yan n li gorî maneyê'') <code>z=mn</code> (''m yan n (bikaranîn dudil e)'') bi kar tînin ([[Şablon:navdêr#Parametre]]) ji ber ku di nav her du nivîsê de pir ferq nebînin. Nizanim em ê dîsa parametreya <code>z=nt</code> (''nêtar'') çêkin, wekî berê: [//ku.wiktionary.org/w/index.php?title=W%C3%AEk%C3%AEferheng:D%C3%AEwan/ar%C5%9F%C3%AEv_2019&oldid=6104681#Zayend]. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 00:17, 28 tîrmeh 2026 (UTC) :Merheba {{r|Ghybu}} {{demo|sep=wisa xuya dibe:<br>|<nowiki>{{navdêr|ku|kelîme|c=mn}}</nowiki>}} Ya din jî; {{demo|sep=wisa xuya dibe:<br>|<nowiki>{{navdêr|ku|kelîme|c=m/n}}</nowiki>}} Tu dixwazî em wana berevajî bikin? Not: nêtar ji bo kurmancî nabe, mn û m/n baş in. Berê ji ber ku m/n tinebû, her kes li gorî parametreyên heyî dixebitî. Niha hene bi min problem nîne eger em berevajî nekin.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 05:32, 28 tîrmeh 2026 (UTC) : Bi min ev format baştir e: {{demo|sep=wisa xuya dibe:<br>|<nowiki>{{navdêr|ku|kelîme|c1=m|c1etîk=Mêrdîn|c2=n|c2etîk=Dihok}}</nowiki>}} Yan jî: {{demo|sep=wisa xuya dibe:<br>|<nowiki>{{navdêr|ku|zayend|c1=n|c2=m|c1ref={{J:Hawar:1998:2|sernav=Ferhengoka Hawarê|nivîskar=Ferhengvan|hj=27|r=696|jêgirtin=Di nav bêjeyên vê Ferhengokê de herçî bêjeyên ko xudan '''zayend''' in, tîpek li ber e. Ew tîp '''zayendê''' bêjeyê şanî dide:m. — mê, n. — nêr.|wekçavkanî=1}}|c2ref={{Zana Farqînî}}}}</nowiki>}} {{çavkanî}} :--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 05:49, 28 tîrmeh 2026 (UTC) ::Feqat em dikarin li şûna {{param2|c|m/n}}, {{param2|c|mn?}} yan {{param2|c|mn!}} çêkin ji bo ku neyên tevlihevkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 06:00, 28 tîrmeh 2026 (UTC) :::Ez jî dizanim ku "nêtar ji bo kurmancî nabe" ([//ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj%3Afikirmend&diff=3063789&oldid=3063526]) jixwe min "nêtar" kiribû "[//ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:fikirmend&diff=prev&oldid=3063788 mê an nêr li gorî bikaranînê]". Feqet nizanim çima rind nayê fêm kirin: Ferhengvan jî ew parametreyê bi awayekî rast bi kar nayîne [//ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj%3Areh&diff=6235991&oldid=6235985]. {{ping|Bikarhêner}} ? Min heta niha pirr gotar serrerastkir... Em ê hertim kontrol bikinê: pêşta problemeke vitira tine bû :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 15:13, 28 tîrmeh 2026 (UTC) ::::Bi rastî kî li vira parametreyên ku te li jor nivîsandine bi kar tîne {{=D}} ? Ji bîr meke em li ser wîkîferhenga kurdî ne... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 15:39, 28 tîrmeh 2026 (UTC) :::::Ya muhîm hebûna sîstemekê ye, heta niha ti sîstemeke baş nehatiye çêkirin û ti rê nehatiye dayîn ji bikarhêneran re ku hîn bibin, hêdî hêdî em ê çi ji destê me were, çêkin û hîn bikin. Bi min atolyeyek lazim e em hin tiştan ji bikarhênerên din re hîn bikin. Mîsal min <code><nowiki>{{subst:beralîbike}}</nowiki></code> li wîkîpediyayê çêkir û ji bikarhênerekî re nîşan da çawa tê bikaranîn, wî dest bi bikaranînê kir. Ji ber ku bikarhênerekî mobîlê ye, nikaribû bi tenê serê xwe beralîkin çêke her daîm alîkarî ji kesên din dixwast ku pir carî ti kes nedihat. Însanên me ji aliyê teknîkî ve baş nebin jî, wextê bi riyeke baş îzah dikî, fam dikim şikir ji xwedê re. :::::Welhasil, [https://ku.wiktionary.org/w/index.php?title=reh&diff=prev&oldid=6291839 reh] çêbû? Eger tu nabêjî nêtar be, min daxwaza te fam nekir. Tu çi dixwazî em çawa bikin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 15:58, 28 tîrmeh 2026 (UTC) ::::::Nivîs dîsa "''mê yan nêr li gorî maneyê''" be (kategorî jî) feqet di nav parametreyê de <code>mn</code> neyê nivîsandin. Parametre wekî {{param2|z/c|nt}} bisekiniyana (an jî navekî din "g" an "c") feqet nivîs û kategorî bihata guhertin... Herwiha profîlên bikarhênerên ku tên vira wekî en.wiki nînin: li vir zêde namînin û tiştên ku hu dikin jî ji bîr dikin. PS: Di zimanê peştûyî de jî (nêzîkî zimanê kurmancî ye) peyvên "mê an nêr" (''common gender'') hene [[:en:Category:Pashto nouns with multiple genders]] [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 17:28, 28 tîrmeh 2026 (UTC) :::::::"g", "c", "nt" gî behsa cureyekî xisûsî dikin loma nabin, feqat di nav [https://ku.wiktionary.org/w/index.php?title=Modul:r%C3%AAziman&oldid=6115355#L-306 Modul:rêziman] de koda me "mn" otomatîk dike "mnmane" min ji bo back-compatiblity wisa kiribû lê ya rast "mnmane" ya, em "mn" ji bo kurmancî rakin, hemû "mn" bikin "mnmane" û "m/n" jî rakin û bikin "mndudil", nabe? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:44, 28 tîrmeh 2026 (UTC) ::::::::OK, bi min baş e:) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 18:18, 28 tîrmeh 2026 (UTC) :::::::::Îmkan heye şablona tewandinê jî wisa bikî ku hem di qismê tewandinê de hem jî aliyê rastê were bikaranîn? Wekî me [[Wîkîferheng:Dîwan/2026#Beşa_Tewandin_bo_kurmancî|li vir]] got? Wextê gelek dirêj be yan mndudil be, em dikarin bixin qismê tewandinê bi şiklê "ya mêr" û "ya nêr". Wekî din yên biçûk û standard bila li aliyê rastê bimînin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:54, 28 tîrmeh 2026 (UTC) ::::::::::Erê bi parametreya {{param2|hêl|çep}} tê çêkirin. Belkî bi JSê tiştekî vitra jî tê çêkirin: dema ku tablo pirr fireh ye (>450px) tablo wekî "veşartî" xuya bike... ::::::::::"''Wekî din yên biçûk û standard bila li aliyê rastê bimînin?''": '''Aliyê rast:''' Dema ku tu mînakan dixwînî bi hêsanî tabloya tewandinê jî seh dikî (pedagojîk e). '''Bin beşa Tewandinê:''' 1) Ji bo mobilan rind e, tablo ne ser maneya peyvê ye. 3) Şûnda maneyan direj dibe 3) Wêne baştir xuya dikin ji ber ku ne bin tabloyê ne. '''Encam''': yek pratîk e, yek jî pedagojîk e [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 19:27, 28 tîrmeh 2026 (UTC) :::::::::::Di bin beşa Tewandinê de baştir xuya dike... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:28, 28 tîrmeh 2026 (UTC) ::::::::::::Erê {{=D}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:29, 28 tîrmeh 2026 (UTC) :::::::::::::Feqat lazim e yên mezin wekî [[mustensîx]] di nav qutîyê de bê wekî [[:en:heval]] di mobîlê de ya me sayfeyê fireh dike, ya îngilîzî de dikarî qutîyê bişemitînî [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:44, 28 tîrmeh 2026 (UTC) ::::::::::::::Formata herî xweş [https://ku.wiktionary.org/wiki/mustens%C3%AEx#Kurmanc%C3%AE] resm jî lê tê tablo jî di cihê xwe de ye. Wekî din wextê tablo li aliyê rastê ye însan naxwaze resmekî jî lê zêde bike. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:54, 28 tîrmeh 2026 (UTC) :::::::::::::::''overflow'' bi tagên "div"-an rind tên çêkirin. Em ê tabloyên ''NavFrame'' bi kar bînin... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:06, 28 tîrmeh 2026 (UTC) ::::::::::::::::Eger class inflection-table bi kar bînî, bi [[MediaWiki:Gadget-defaultVisibilityToggles.js#L-43]] ê ku dixwaze dikare gîya veşêre an nîşan bide. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:11, 28 tîrmeh 2026 (UTC) :::::::::::::::::Min fêm nekir, biryara we çi ye? Hemû bin beşa Tewandinê? an jî herdu? Li gor wê şablon tê guherandin. Bi min ferq nake, her du jî baş in... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:19, 28 tîrmeh 2026 (UTC) ::::::::::::::::::Me [[#Beşa Tewandin bo kurmancî|li jor]] gotibû bila hemû di beşa Tewandinê de bin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:21, 28 tîrmeh 2026 (UTC) :::::::::::::::::::Erê, min xwand Bikarnêner tiştekî din gotibû... Tu bi botê çêdikî? Bi botê hemû tabloyan bê parmetreya "hêl" bike bin beşa "Tewandin"-ê. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:30, 28 tîrmeh 2026 (UTC) ::::::::::::::::::::Va rabim botekê hazir bikim. Bi qasî min jê fam kir, tam nabêje hemû nekin, nabêje hemû bikin jî. Lê em hemû bikin çunkî du kes got erê. Cihê Tewandinê piştî Bi alfabeyên din û Formên alternatîv be an jî beriya wan piştî maneyê (piştî wajeya klasîk) be? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:38, 28 tîrmeh 2026 (UTC) :::::::::::::::::::::Eger di yekcarê de nayê çêkirin bi parametreya "hêl" ve çêke. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:42, 28 tîrmeh 2026 (UTC) ::::::::::::::::::::::[https://linkcount.toolforge.org/?project=ku.wiktionary.org&page=%C5%9Eablon%3Aku-tew%C3%AEn-nav 27 hezar] car tê bikaranîn, Eger behsa wextê dikî, ne problem e, eger behsa "tenê yên fireh bixin tewandinê" wê carê yên mê û nêr bixim? Te cewaba pirsê cihê tewandinê jî neda? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:48, 28 tîrmeh 2026 (UTC) :::::::::::::::::::::::Lojîk dibêje ku piştî bi "alfabeyên din", "formên alternatîv" û "Ji wêjeya klasîk" [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:55, 28 tîrmeh 2026 (UTC) ::::::::::::::::::::::::Feqet tabloya tewandinê dûr dikeve... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:00, 28 tîrmeh 2026 (UTC) :::::::::::::::::::::::::Bi min "Bi alfabeyên din" bixin piştî Bilêvkirinê çûnkî @[[Bikarhêner:Ferhengvan|Ferhengvan]] pir caran ji bo nîşandana dengî alfaba erebî bi kar tîne, h3 rengê teal tenê ji bo "Navdêr, Lêker hwd." bi cssê bi kar bînin [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/vector-2022.css&diff=prev&oldid=6241199 wekî wisa lê berevajî], Piştî "Ji wêjeyê/klasîk" em tewandinê deynîn, "Formên alternatîv" piştî Tewandinê be û îro nekin, eger dixwazî di ceribandinê de tabloya nû hazir bike, em hefteyek li hêviya hevalên din bisekinin, eger îtîraz nehat, em çêkin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:15, 28 tîrmeh 2026 (UTC) ::::::::::::::::::::::::::Beşa "Bikaranîn" jî heye... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:28, 28 tîrmeh 2026 (UTC) :::::::::::::::::::::::::::Piştî Bikaranînê bnr. [[:en:Wiktionary:Entry_layout#Headings_after_the_definitions]] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:37, 28 tîrmeh 2026 (UTC) ::::::::::::::::::::::::::::(h3) Bilêvkirin, Bi alfabeyên din, Sinifa rêzimanî, ::::::::::::::::::::::::::::(h4) Ji wêjeyê/klasîk (divê were xistin bin maneyê), Bikaranîn, Tewandin, Formên alternatîv, Hevmane, Nêzîk, Dijmane, Jê, Têkildar, Etîmolojî (eger du sinifa rêzimanî ji eynî kokê hebe h3) Dûnde, Binêre herwiha, Werger [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:40, 28 tîrmeh 2026 (UTC) {{outdent|::::::::::::::::::::::::::::}} {{r|Ferhengvan|Bikarhêner|Keyomerd|Zerwanda|Kurdanparez}} Fikir? --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:42, 28 tîrmeh 2026 (UTC) :"Bi alfabeyên din" beşeke pirr hewce nîne, niha beşa "mane" li ser rûpelê dûr dikeve. Bi min "Bîlêvkirin" > Mane > Ji wêjeya klasîk (wekî mînak e) > Bikaranîn > Tewandin > Bi alfabeyên din > Formên alternatîv > ... Divê beşên ku herî zêde tên xwastin werin "ronîkirin". [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 03:07, 29 tîrmeh 2026 (UTC) ::''[[bileks|Bîl'eks]],'' "Bi alfabeyên din" gelek muhîm e, ev ji bo kurmancî "formên alternatîv"-a wîkiya îngilîzî ye, başûrî tenê bi alfaba erebî dinivîsin û wextê kelîmeyek digerin çawa zanibin hatin kîjan kelîmeyê? Bi kirîlî ne lazim e lê bi erebî mecbûrî ye. Ji bo nettir bikin, lazim e em beşa "Bi alfabeyên din" baştir bikin. Mane hinek li jêr be ne muhîm e, wîkiya îngilîzî de jî gelek car lazim e herî jêr ji bo dîtina maneyê. "Ronîkirin"/teal xelet tê famkirin, sankî "qismê sereke (h3) lazim e wê be û qismên din werin xistin binê wê" tê famkirin loma em tenê Mane ronî bikin bes e, ka [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/common.css&oldid=6291927 vê cssê] biceribîne û dîsa fikrên xwe bibêje. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 07:20, 29 tîrmeh 2026 (UTC) :1. '''Li ser cinsîyetê:''' Bi min, em malûmatên ekstra yên wek ''"li Dihokê nêr, li Serhedê mê"'' (Serhed:m|Dihok:n) li qismê ''"Bikaranîn/Emilandin"''ê bidin baştir e. Kelîme di ferhengan de wek form û cinsîyet bi halê standard cih digirin, eger li mintiqayek cuda be ew cudahî li qismê "Bikaranîn/Emilandin"ê wek malûmatek ekstra cih bigire çêtir e. Ferhenga ku em vê gavê ji bo standardkirinê esas digirin ''"Ji bo Rastnivîsînê Ferhenga Kurdî (Kurmancî) - Tirkî ya Nû"'' de jî bi yek cinsîyetê cih dane kelîmeyan. Ji xeynî wê di ferhenga standardkirinê ya Weqfa Mezopotamyayê de jî ew kelîme bi yek cinsîyetê cih digirin. Tiştekî din jî bêjim, eger em şablonê wek "mndudil" bi nav bikin mimkin e ku rê bide şaşîyan. Çimkî gava mirov wê dibîne, mirov dibêje qey li ser cinsîyeta kelîmeyê dudilîyek heye, bi qenaeta min dudilîyek bi wî şiklî nîne. Divê her kelîme xwedî cinsîyetekê bin û îstîsnayên mintiqayî -ger were xwestin- ekstra were nîşandan. Lewma bi min halê mewcûd baş e. 2. '''Li ser şablonên tewandinê:''' Ger şablonên tewandinê di xuyabûna mobîl de bibin sedema xirabîyê, em wan şablonan ji bo mobîlan têxin qismê "Tewandin"ê. 3. '''Li ser rêzkirina qisman:''' Bi min divê mane li pêş be û ne hewce ye ku qismê "Bi alfabeyên din" derxin pêş. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 13:20, 29 tîrmeh 2026 (UTC) ::Li ser cinsiyetê erê, eger di ferhenga rastnivîsînê de cinsiyet hatibe nivîsandin ne hewce ye em "mndudil" binivîsin li qismê Bikaranînê behskirin bes e, lê eger tê de ev kelîme tinebe û di ferhengên din de jî dudiliyek li ser bikaranîna cinsiyetê hebe, wê demê "mndudil" lazim e bikaranîn çunkî wîkîferheng lazim e li gorî çavkaniyan were nivîsin. Li ser tewandinê ne mimkûnê em di mobîlê de di qismê Tewandinê de, di sermaseyê de em li qismê maneyê bixin loma lazim e em bi yek şiklî li qismê Tewandinê hemû bixin çêtir e. Li ser "Bi alfabeyên din" ji bo min zêde muhîm nîne, feqat dîsa jî ez dibêjim lazim e were pêşxistin. Tiştekî wisa jî heye eger di sayfeyekê de ji yekî zêdetir sinifên rêzimanî hebe wê demê lazim e Bi alfabeyên din bi sê = were bikaranîn, û cihê wê ne li dawiyê lê divê piştî Bilêvkirinê be.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:45, 29 tîrmeh 2026 (UTC) :Bi a min beşa çevandinê li serê rûpelê be beşa maneyê pir dûrî çavan dikeve. Li jêrtir be çêtir e. [[Bikarhêner:Keyomerd|Keyomerd]] ([[Gotûbêja bikarhêner:Keyomerd|gotûbêj]]) 06:01, 31 tîrmeh 2026 (UTC) ::{{r|Wikihez}} Bi min di nav tabloyê de parametreya yekem jî were rakirin, ne hewce ye bi <nowiki>{{PAGNAME}}</nowiki> tê çêkirin. Di rûpelên din de jî (ne yên sereke) bi parametreya {{param2|nav}} were nivîsandin. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 11:07, 31 tîrmeh 2026 (UTC) :::Erê, maqûl e. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:23, 31 tîrmeh 2026 (UTC) ::::cinsiyet jî m, n, mn be bes e ma bila wekî {{ş|navdêr}} be. cuda nebin [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:41, 31 tîrmeh 2026 (UTC) :::::@[[Bikarhêner:Bikarhêner|Bikarhêner]], @[[Bikarhêner:Keyomerd|Keyomerd]], @[[Bikarhêner:Ghybu|Ghybu]] "Bikaranîn" an "Notên bikaranînê" ? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:47, 31 tîrmeh 2026 (UTC) :::::Wekî {{r|Bikarhêner}}î gotî zayenda peyvnan gorî devokan jî diguhere, divê ew jî bêne dîyarkirin. Herwiha beşa lêvandinê a ji bo pîtên cêwî pir tê paşguhkirin. Divê jê re cîyekî cihê bê hilanîn. Û ew jî wek zayendê bi devokan diguhere. Meselen tya pêşîn a "tişt" ê li ba me nerm e lê li deverên din hişk e. Û ji devla reqê (wek t-ya req) hişk bi kar bê çêtir e, jixwe her kes wê bi kar tîne nizanim req ji ku derketîye. [[Bikarhêner:Keyomerd|Keyomerd]] ([[Gotûbêja bikarhêner:Keyomerd|gotûbêj]]) 14:05, 31 tîrmeh 2026 (UTC) : <syntaxhighlight lang="json"> "subsections": [ "Ji wêjeya klasîk", "Ji wêjeyê", "Bikaranîn", "Tewandin", "Bi alfabeyên din", "Formên alternatîv", "Kurtkirin", "Sembol", "Navê zanistî", "Hevmane", "Dijmane", "Jê", "Nêzîk", "Jornav", "Jêrnav", "Têkildar", "Etîmolojî", "Dûnde", "Binêre herwiha", "Bi zaravayên din", "Werger", "Qafiye", "Anagram" ] </syntaxhighlight> {{r|Keyomerd|Ghybu|Bikarhêner}}Li gorî nîqaşa jor û [[Alîkarî:Formata nivîsînê]] min ev lîste hazir kir lê tê de hin kêmasî hene, "Bide ber" tê de tine ye, li kû derê bixim? Mihtemelen beşên din jî hene ku haya min ji wan nîne. Pirsek din, beşên nestandard wekî [https://ku.wiktionary.org/w/index.php?title=berf&diff=prev&oldid=6292461] çi bikim? Min got li dawiyê bixim berî Wergerê lê sankî piştî Wergerê be çêtir e?--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:24, 31 tîrmeh 2026 (UTC) :@[[Bikarhêner:Bikarhêner|Bikarhêner]], @[[Bikarhêner:Ghybu|Ghybu]], @[[Bikarhêner:Keyomerd|Keyomerd]] Eger îtîraz an fikrekî din neyê, ez ê beşên nestandard bixim beriya "Bi zaravayên din" eger ev beş tinebe, beriya "Werger". Ez ê "Nêzîk" jî bixim piştî Hevmane û li ser [[Alîkarî:Formata nivîsînê]] "rast" bikim. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:50, 1 tebax 2026 (UTC) ::Ez ê "Bikaranîn" jî bikim "Notên bikaranînê" [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:03, 1 tebax 2026 (UTC) :::Jixwe bot hema bêje hazir e, eger dûre kesek rabe fikrekî din li pêş bixe, em dikarin biguherînin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:04, 1 tebax 2026 (UTC) ::::Ev hinek zêdetir problematîk e feqat ez ê "Ji wêjeyê/a klasîk" jî bikim "Ji edebiyatê"/"Ji edebiyata klasîk". Tabî eger fikrekî din hebe, ne problem e. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:05, 1 tebax 2026 (UTC) :::::Na, bi min "wêje" bimînî... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 01:22, 1 tebax 2026 (UTC) ::::::Ok {{=D}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:23, 1 tebax 2026 (UTC) :::::::"Bide ber" pêşiya "Binêre herwiha" :::::::"Jê" pêşiya "Têkildar" piştî jornav, jêrnav [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:41, 1 tebax 2026 (UTC) :::::Ji bo min "'''edebîyat'''" çêtir e, bila ne wêje be. "wêje" kelîmeyeke şaşçêkirî ye. Mahîyeta qisman (kîjan qism bi kêrî çi tê) ji navên wan nayê famkirin. "Binêre herwiha" û "Herwiha" tevlihev dibû, baş e we rast kirîye. Feqet mahîyeta wê qismê ("Binêre herwiha") hê jî ji navê wî nayê famkirin. Jixwe ger em bixwazin bi wî şeklî binivîsin jî divê em bikin "Herwiha binêre", ew jî zid hatîye nivîsandin. Ji xeynî wê, "Navê zanistî" na, "'''Navê îlmî'''" çêtir e. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 22:51, 2 tebax 2026 (UTC) ::::::Bi min beşa Navê zanistî werin rakirin, wekî en.wikt em li dawiyê yan li pêşiya maneya bi şablona {{ş|q}} binivîsin yan jî wê şablona îngilîzî çêkin ku enwikt bi kar tîne. ::::::Li wikipediyayê min çend car dîtiye Penaber49 jî "Binêre herwiha" dike "Binêre" loma guhartina wê wekî "Herwiha binêre" fikrekî maqûl e. ::::::Herwiha tu ji bo Bêhtir xwendin çi dibêjî [[Special:PermanentLink/6323554#Binêrê_herwiha]] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:29, 3 tebax 2026 (UTC) :::::::Ez dibêjim bila '''''"Xwendina Zêdetir"''''' be. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 05:03, 6 tebax 2026 (UTC) :::Em çima peyva notê bi kar tînin, ma "nîşeyên bikaranînê" ne çêtir e? [[Bikarhêner:Keyomerd|Keyomerd]] ([[Gotûbêja bikarhêner:Keyomerd|gotûbêj]]) 06:04, 1 tebax 2026 (UTC) :Rêzkirina dawî: <syntaxhighlight lang="json"> "subsections": ["Ji wêjeya klasîk", "Ji wêjeyê", "Tewandin", "Notên bikaranînê", "Bi alfabeyên din", "Formên alternatîv", "Kurtkirin", "Sembol", "Navê zanistî", "Hevmane", "Nêzîk", "Dijmane", "Jornav", "Jêrnav", "Jê", "Têkildar", "Etîmolojî", "Dûnde", "Bide ber", "Binêre herwiha", "Bi zaravayên din", "Werger", "Qafiye", "Anagram"] </syntaxhighlight> Bnr. [[Wîkîferheng:Bot/Balyozbot/tercîh.json]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:44, 1 tebax 2026 (UTC) :Bi botê ez ê tenê binebeşên sinifên rêzimanî yên bi 4 = biguherînim, yên din lazim e bi destî werin guhartin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:46, 1 tebax 2026 (UTC) ::@[[Bikarhêner:Ghybu|Ghybu]] Bota rêzkirina binebeşan û cihguhartina Tewandinê hema bêje hazir e. Param {{param|hêl}} bi kar bînim (eger wisa be, em kategoriya "ku-tewîn-nav bê param hêl" çêkin daku hemû xilas bikin) yan jî şablonên heyî bikim ku-tewîn-nav/kevn û piştî kontrolkirinê hemû bikin nû? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:26, 1 tebax 2026 (UTC) :::Bi parametreyê {{param2|hêl}} tu ê paşê wan dîsa rakî... Herwiha min va [https://ku.wiktionary.org/w/index.php?title=abes%C3%AEv&curid=43641&diff=6294632&oldid=6244736] fêm nekir, me çima Tabloya tewandinê rakir :)? [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:26, 1 tebax 2026 (UTC) ::::Ji bo ku rê bidin tiştên wisa :D Em ê li kû derê deynîn examples?? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:28, 1 tebax 2026 (UTC) :::::Tablo hazir bin, em dest pê bikin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:28, 1 tebax 2026 (UTC) ::::::Sernav tê rakirin, mê bikim "m"? yan bila bimînî? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:28, 1 tebax 2026 (UTC) :::::::Tablo hatiye çêkirin bi [https://ku.wiktionary.org/wiki/Modul:ku-tew%C3%AEn-nav/ceribandin vê] kodê her du parametre jî tên bikaranîn mê/m, nêr/n û mê û nêr/mn... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:41, 1 tebax 2026 (UTC) :::::Ez nizanim çi bibêjim... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:43, 1 tebax 2026 (UTC) ::::::[https://ku.wiktionary.org/w/index.php?title=abes%C3%AEv&diff=prev&oldid=6294657] ok? ::::::Bi min li şûna {{param|hêl}} em {{ş|ku-tewîn-nav/nû}} bi [[Modul:ku-tewîn-nav/ceribandin|modula ceribandinê]] çêkin, paşê navê şablonê biguherînin baştir be, çunkî [[Special:PermanentLink/6294527#L-337|modula nû]] ne backward compatible e. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:56, 1 tebax 2026 (UTC) :::::::Em ê dîsa paşê nivîsa "/nû" rakin. Bi botê 22000 rûpel di 2 rojan de tê guherandin? Eger wisa ye (bi min pirr nîne), bi navê rast biguhrîne, bila di nav rûpelên ku nehatine guherandin xeletî hebin... Dîsa jî tu dizanî, bot te çêkiriye û tu sererast dikî :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:17, 1 tebax 2026 (UTC) ::::::::Min gelek caran dîtiye, bi botê tiştekî hatiye guhartin lê ji ber ku rind nehatiye kontrolkirin, şablona kevn bi halê xwe yê kevn maye. Tirsa min ew e. Ji ber ku formata hemû sayfeyan ne eynî ne, ez dibêm bot gelek ji wan derbas bike. Bi vî awayî em ê {{ş|ku-tewîn-nav}} sêwî bihêlin û piştî bot xilas kir, em ê bi dil rehetî karibin şablona nû rakin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:26, 1 tebax 2026 (UTC) :::::::::Rast e! {{param|g|2}} :)) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:32, 1 tebax 2026 (UTC) ::::::::::Mîsalên wan gelek in :) [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:36, 1 tebax 2026 (UTC) :::::::::::Eger karibî hinek round edges bixî û rengê background a "Tewandina X" biguherînî, gelek moderntir û xweştir xuya bike :) [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:25, 1 tebax 2026 (UTC) ::::::::::::''Simplicity is best'' / ''Fewer choices mean less worry:'' felsefeya min e:) Me tabloyê wekî en.wîkî kir [https://ku.wiktionary.org/wiki/%C5%9Eablon:tabloya-tewandin%C3%AA-ser {tabloya-tewandinê-ser}], tenê [//ku.wiktionary.org/wiki/Modul:ku-tew%C3%AEn-nav/ceribandin#L-362 reng] ({{param2|palette}}) tê guherandin (felsefeya wan e jî...). Bi min tiştekî pir rind çêkirine. Dîsa jî em dikarin (wekî berî) bi CSSê biguherînin. Ji bo çêkirina tabloyan min di rûpela şablonê de tiştên ku pirr hewce ne nivisandiye ji bo detayan jî rûpela en.wiki heye. Herwiha tabloyê li gor daxwaza we biguherînin û serrast bikin. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 03:04, 2 tebax 2026 (UTC) :::::::::::::PS: Şiklê tabloyê li vira tê guherandin [[Şablon:tewandin-ser/style.css]] [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 04:41, 2 tebax 2026 (UTC) ::::::::::::::Mala te ava tu ji heqê rengan gelek xweş derdikevî :) ::::::::::::::Ev felsefeya te gelek caran karê min pir zor dike {{=D}} en.witk gelek tiştî bi awayekî xweş çêkirine, ez jî heta ku wana adapte bikim, gelek êş dikşînim bnr. [[#Modul:quote]] û Şablonên etîmolojiyê [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 10:47, 2 tebax 2026 (UTC) :::::::::::::::Bot xilas kiriye, Baş e [[Special:PermanentLink/6323268#Şablona_ku-tewîn-nav_ne_li_binê_Serenav_an_Navdêrê_ye|zêde]] xeletî derneketin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:35, 2 tebax 2026 (UTC) ::::::::::::::::Gelek spas! [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:42, 2 tebax 2026 (UTC) :::::::::::::::::Niha şablon sêwî ma ji xeynî gotûbêjan, ew jî dûrê rast bikim, tu dikarî modulan rojane bikî? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:28, 3 tebax 2026 (UTC) ::::::::::::::::::Spas. Ev rûpel pirr dirêj bû... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 00:33, 3 tebax 2026 (UTC) :::::::::::::::::::Erê, rêzkirina beşan ez ê bikim yek satir, lê dîsa jî zêde fêde nede, fikrekî din heye? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:38, 3 tebax 2026 (UTC) ::::::::::::::::::::@[[Bikarhêner:Ghybu|Ghybu]] [https://ku.wiktionary.org/wiki/W%C3%AEk%C3%AEferheng:D%C3%AEwan#c-Wikihez-20260801005000-Wikihez-20260731162400] û [https://ku.wiktionary.org/w/index.php?title=gur&curid=5384&diff=6328092&oldid=6328089] ? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:00, 7 tebax 2026 (UTC) :::::::::::::::::::::@[[Bikarhêner:Ghybu|Ghybu]] Rêza notên bikaranînê [https://ku.wiktionary.org/w/index.php?title=neyam&diff=next&oldid=6340610] biguhêrînim? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:25, 22 tebax 2026 (UTC) == SEO == Merheba @[[Bikarhêner:Ghybu|Ghybu]] Wextê ''jiyannas'' bi şiklê "jiyannas" lê digerî di nav netîceyên googlê de [[jiyannas]] derdikeve? Min hem bi Chromeê û hem jî bi VPNê ceriband lê [[jiyannaseke]] derdikeve feqat [[jiyannas]] dernakeve. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:31, 2 tebax 2026 (UTC) :"zengilok" derdikeve [[zengilok]] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:38, 2 tebax 2026 (UTC) :Min jî tenê [https://usercontent.one/wp/portal.arsivakurd.org/wp-content/uploads/2024/08/Bernamegeh-4.pdf?media=1709107483 va] (''Berna Megeh'', Jan Dost, OCCO MAHABAD) û https://portal.arsivakurd.org/wp-content/uploads/2022/06/Xwebun-34.pdf va] (''Xwebûn'', hj.34) dît herwiha ''Jihannasî'' jî heye... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:44, 2 tebax 2026 (UTC) ::Behsa çavkaniyan nakim behsa SEOyê dikim, çima [[jiyannas]] di netîceyan de dernakeve. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:49, 2 tebax 2026 (UTC) :::Min fêm nekir, pirsa te çima Wîkîferheng dernakeve ye? [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 20:51, 2 tebax 2026 (UTC) ::::Erê çima sayfeya Wîkîferhengê ya [[jiyannas]] dernakeve feqat [[jiyannaseke]] derdikeve. Min du nimûne nivîsandin ka piştî mehekê em binêrin derkeve yan na. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:54, 2 tebax 2026 (UTC) :::::Bi min dema ku motora googlê "jiyannaseke" (-eke bi kurdî ye) digere, ew peyv tenê di kurdî de heye ji ber vê yekî dide. Feqet "Jiyannas" di nav zimanên din de jî heye (belkî difikire ku ew xeletî ye.). Herwiha nivîsa bin "Jiyannas" li gor "jiyannaseke" biçûk e û li bin "biolog" hatiye nivîsandin:) Herwiya peyva "biolog" jî dide ew jî giridayî pirr peyvan e... Pirr parametre hene... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:09, 2 tebax 2026 (UTC) ::::::Wextê li "birakujî" dictionnaire digerî netîceya ewil rasterast fr.wikt e. Wana tiştekî kirine lê çi? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:13, 2 tebax 2026 (UTC) :::::::"Trust Score" ? Herwiha peyva "birakujî" pêş Wîkîfehengê hatiye çêkirin. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:21, 2 tebax 2026 (UTC) ::::::::Nizanim [[:en:Wiktionary:Votes/2023-08/Installing the WikiSEO extension]] heye lê [[:phab:T346590]] sekinî ye. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:27, 2 tebax 2026 (UTC) :::::::::Erê, feqet lînkên û navên Wîkîferhenga fransî û îngilîzî di internetê de pirr tên parvê kirin. Wîkîferhenga fansî ferhengek derxistiye: [https://www.fnac.com/a13530183/Collectif-Le-dico-adapte-du-Wiktionnaire Le dico] (li ser Amazonê). Kî qala Wîkîferhenga kurdî dike? Ji ber vê yêke hertim pêş me ne. Daxwaza wan werin pêş malperên din... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:36, 2 tebax 2026 (UTC) ::::::::::[https://www.google.com/search?sca_esv=a854c327b7bb0786&q=%22W%C3%AEk%C3%AEferheng%22&tbm=nws&source=lnms&fbs=ABfTbFUDadgeu2mn4mYJ8iEZ1GUDDuwRa4um-2LNhBFWIpqZc7ZL_t3iAe0lB1D4hb_Ohp7yg8FO-XwZ7R-ba4YefvIQCF4Ra4wbUNQStQ8dVc6IK2vWHoXbgHLwJobq4HTNMksBhYHBmxw2hK9Sa4pHAI3I2Ovzox54EiEId7q7IoMJRkRlr-XDezqDqx33xDsZIWuHy-a_vqoqDlYrhNBbNeVEP9MwaA&sa=X&ved=2ahUKEwiz94Co9IKWAxXNUaQEHQJAAGYQ0pQJegQIGBAB&biw=1320&bih=583&dpr=1 Wîkîferheng] {{=D}} Li ser X û medyayên din de jî pirr qala Wîkîferhengê nakin... Bi rastî kî Wîkîfrhengê dixwîne? [https://pageviews.wmcloud.org/topviews/?project=ku.wiktionary.org&platform=all-access&date=yesterday&excludes=]... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:41, 2 tebax 2026 (UTC) :::::::::::Haya ti kesî ji Wîkîferhengê nîne bi rastî loma pêşxistina SEOyê hewce ye. Ez dibêjim miheqeq fr.wikt tiştek çêkiriye ne mimkun e wextê heval dictionnaire binivîsî wiktionary derkeve bêyî çêkirina tiştekî. Not: Min ferq kir li ser fr.wikt wextê bi mobîlê tê dikevî, eger di sayfeyekê de du ziman hebe ya fransî otomatîk vedibe zimanê din veşartî dimîne. Fikrekî xweş e em jî çêkin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:21, 2 tebax 2026 (UTC) ::::::::::::Erê bila were çêkirin. Min gotûbêja wan li ser vê mijarê xwandibû, Wîkîferhenga fransî jî ne razî ye. Dema ku li ser Googlê tu peyvek diguherî Wîkîferhenga wan di bin Wîkîpediyayê û di bin malperên din de derdikeve. Û çend caran şûnda "Wiktionnaire" "Wikipédia" tê nivîsansin... Ew jî nizanin çi bikin :)) Niha dizanim ku en.wikt ji ne razî ye... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:37, 2 tebax 2026 (UTC) :::::::::::::@[[Bikarhêner:Ghybu|Ghybu]], @[[Bikarhêner:Wikihez|Wikihez]]: Ez dibêjim rûpelên ku tenê form di wan de hene, divê <nowiki>__NOINDEX__</nowiki> bin. Wî çaxî, rêza wan nikare ji lemmayê bilindtir be ji ber ku wê nînbin. Ez dibêjim belkî îhtîmala derketina lemmayê bêhtir jî bibe heke netîceyên ku dişibin wê nînbin. Jixwe lemma wê derkeve heke yek li formekê bigere, ji ber ku di rûpelê lemmayê de tabloyên tewandinê hene û ev tên jimartin. [[Bikarhêner:Guherto|Guherto]] ([[Gotûbêja bikarhêner:Guherto|gotûbêj]]) 22:55, 2 tebax 2026 (UTC) ::::::::::::::@[[Bikarhêner:Guherto|Guherto]] Em dibêjin tenê form xuya dike ya sermade xuya nake tu dibêjî em formê noindex bikin {{=D}} ::::::::::::::Claude [[Special:PermanentLink/6323375|li vir]] dibêje ya ku Ghybu got rast e, ji ber ku frwikt gelek tê bikaranîn bêtir dikeve ber çavê google. Eger rojek Wikiseo li en.wikt were çêkirin, em jî bixwazin qet nebe kêrî tiştekî were. ::::::::::::::Em şablonek ji bo metadescription çêkin? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:09, 2 tebax 2026 (UTC) :::::::::::::::@[[Bikarhêner:Wikihez|Wikihez]] Min got, ''Wî çaxî, rêza wan nikare ji lemmayê bilindtir be ji ber ku wê nînbin. Ez dibêjim belkî îhtîmala derketina lemmayê bêhtir jî bibe heke netîceyên ku dişibin wê nînbin.'' [[Bikarhêner:Guherto|Guherto]] ([[Gotûbêja bikarhêner:Guherto|gotûbêj]]) 23:10, 2 tebax 2026 (UTC) :::::::::::Em jegirtinan lînk bikin? Bi vî sayî gelek sayfe lînk bide ser hev. Bi riya cssê em dikarin rengê tarî bikin da ku wekî lînk xuya nekin... [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:39, 3 tebax 2026 (UTC) ::::::::::::Wextê jîwar ferheng yan jî boçik ferheng lê digerî rasterast Wîkîferheng dertê. Meselê hejmara bikaranîna eynî kelîmeyê di sayfeyê de ye. Em çiqas jêgirtin lê zêde bikin ewqas baştir dibe netîce :) Google AI Mode rasterast Wîkîferheng wek çavkanî nîşan û lînk dide loma kurmanc bi kar neyînin jî AI bi kar tînin baş e ... [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:24, 3 tebax 2026 (UTC) :::::::::::::Êêêê Google AI Overview çi bi şikle "tarîxiyen" ferheng lê digerim wekî ku min li ferhengê qeyd kiriye gelek xweş îzah dike (ji ber ku hîn gelek nû ye netîceyan de Wîkîferheng dernakeve) Nimûneyên bikaranînê jî ji înternetê derdixe. Çi mana ferhengê nemaye... Em çi îşî dikin li vir :D [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:47, 3 tebax 2026 (UTC) :::::::::::::Êdî Google jî nayê bikaranîn :)) Niha kî tere ser ''Stack Overflow'' û di nav belgeyên kodan de digere... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 21:47, 3 tebax 2026 (UTC) ::::::::::::::Erê welle, ez gelek car dibînim kesên derdora min hemen Gemini an Chatgpt vedikin, çi tiştê biçûk hebin, hemen pirs dikin, qet li ser Googlê jî lê nagerin :D [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:52, 3 tebax 2026 (UTC) :::::::::::::::"êgsig ferheng" netîce nade feqat wexta "ornag ferheng" digerim rasterast wîkîferheng derdikeve li binê dibêje "Tewandina ornag. Zayenda nêr a binavkirî. Rewş, Yekjimar, Pirjimar. Navkî, ornag, ornag. Îzafe, ornagê · ornagên. Çemandî, ornagî · ornagan.Read more" :::::::::::::::Meraq dikim guhartina cihê tewandinê çi netîce bide. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:21, 3 tebax 2026 (UTC) ::::::::::::::::Pêşta me tabloya Tewandinê vitira dinivîsand: [[ketin (Tewandin)]] Dma ku nav hat guherandin li ser Googlê tewandin winda bû... ::::::::::::::::Min tewandin:kirin geriya tabloya tewandina Wîkîferhengê dide. Êdî kes nê vira:) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:38, 3 tebax 2026 (UTC) :::::::::::::::::Tenê dema "niha" nivîsand. Min jî bi kurdî "dema bê jî binivîse" nivîsî: ew jî nivîsand... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 22:42, 3 tebax 2026 (UTC) ::::::::::::::::::[https://support.google.com/webmasters/answer/16908024?hl=en tê asteng kirin]... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 02:07, 4 tebax 2026 (UTC) :::::::::::::::::::kî dibêje? li wir tiştek wisa nabêje...? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 02:16, 4 tebax 2026 (UTC) ::::::::::::::::::::Va hatiye nivîsandin: "''Exclude my site's links and content from Search generative AI features: Your site's content is prevented from being visible to users in Search generative AI features, including being linked to within these features and helping with grounding AI responses in these features. You won't receive any traffic or impressions from these features. Learn more about what excluding your site means.''" [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 02:23, 4 tebax 2026 (UTC) == Moda tarî == Bi chrome û Firefoxê wextê Reng dikî "otomatîk", eger tarî be, tiştên bi reng xirab xuya dikin, lê wextê "tarî" hildibijêrî xweş xuya dikin. Min hemû js/css/Gadget betal kirin û ?safemode=1 ceriband, dîsa jî wextê "otomatîk" e, her tiştê tarî xirab e. Êdî nizanim problem li cem min e yan di Moda tarî de ye. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:15, 9 tebax 2026 (UTC) == Formata jêgirtinan == Merheba hevalno {{r|Ghybu|Bikarhêner|Keyomerd|Kurdanparez|Guherto|Şêr}} Wekî min [[#Modul:quote|li jor]] jî gotiye, formata îngilîzî ji ya me baştir e. Her tişt di cihên xwe de ne. Ya me wexta çend tercime yan jî transliterasyon îlawe dikî, gelek tevlihev dibe. Berê me çavkaniyê bi amûra [[MediaWiki:Gadget-jeder.js]] kurt kiribû feqat ew jî ne tiştekî baş e ji ber ku gelek malûmat tên veşartin û kesên nû tên tenê sal û nivîskarê dinivîsin carinan ew jî ne tiştekî baş e. Em dikarin amûra jêderê wisa eyar bikin ku bêyî parentez bixebite û ewilî vekirî be, dûre ê ku dixwaze malûmatan kurttir bike. Eger em vî tiştî bi formata me ya niha bikin, jêgirtinên bi çavkaniyên dirêj dê gelek xirab xuya bikin. Hûn dikarin li vir miqayese bikin ka kîjan baştir xuya dike: # [[Special:PermanentLink/6329434|jêgirtina dirêj bi îngilîzî bi formata en.wikt]] vs. [[Special:PermanentLink/6329414|bi formata me ya niha]] # [[Special:PermanentLink/6329439|jêgirtineke bi soranî bi formata en.wikt]] vs. [[Special:PermanentLink/6329437|jêgirtineke bi soranî bi formata me ya niha]] Ez naxwazim xwe wisa nîşan bidim ku li ser eynî tiştî her daîm israr dike feqat bi ya min ev zarûriyeteke ji bo baştirkirina xwendina nimûneyan e. Loma ez li vir dengdanek li dar dixim, bila qerar çi be, em wisa bikin, dûre em dikarin amûreke nû çêkin ku li gorî tercîhên bikarhênerî formata en.wikt yan jî formata niha were bikaranîn. Ji kerema xwe raya xwe li jêr bidin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:01, 11 tebax 2026 (UTC) === Dengdan === {{dengdan/borî|destpêk=11.08.2026|dawî=18.08.2026}} <!-- kengî dengdan xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bila formata niha bimîne ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo raya erê. --> ==== Bila formata en.wikt were bikaranîn ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo raya erê. --> # {{erê}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:05, 11 tebax 2026 (UTC) # {{erê}} [[Bikarhêner:Keyomerd|Keyomerd]] ([[Gotûbêja bikarhêner:Keyomerd|gotûbêj]]) 14:40, 16 tebax 2026 (UTC) === Gotûbêj === {{şirove}} Eger hûn bibêjin çima sal û çavkanî li herî pêş e sebeb ev e: Ji bo en.wiktê "attestion" yanî peyitandin bi riya emilandinên heqîqî pêk tê. Yanî eger di ferhengekê de ev kelîme derbas bibe ji bo wan ne muhîm e, ya muhîm emilandina di nav cumleyan de ye. Mîsal ew kelîmeyên ku tenê ferhengan de derbas dibin dixin [[:en:Appendix:English dictionary-only terms]]. --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:14, 11 tebax 2026 (UTC) :@[[Bikarhêner:Ferhengvan|Ferhengvan]], @[[Bikarhêner:Bibliophile|Bibliophile]] û @[[Bikarhêner:Dûrzan|Dûrzan]] fikrê we çi ye li ser vê meseleyê? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:48, 12 tebax 2026 (UTC) ::Ez ji tiştên teknîk pirr fêhm nakim. Çewa baş be ên ku pispor in bila biryar bidin... [[Bikarhêner:Dûrzan|Dûrzan]] ([[Gotûbêja bikarhêner:Dûrzan|gotûbêj]]) 21:04, 12 tebax 2026 (UTC) == Guhartina rêbaznameyê == Ez fam nakim me çima di rêbaznameyê de gotiye twitter nayê hesibandin wextê çavkanîdayînê. en.wikt bi kar tîne û eger wek cimleyek derbas bibe bi min ti problem nîne. Fikr? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:06, 14 tebax 2026 (UTC) :Heta twitter ji bikaranîna ferhengan hîn baştir e, qet nebe em emilandina kelîmeyekê ya eseh dibînin... [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:07, 14 tebax 2026 (UTC) ::Merheba @[[Bikarhêner:Ghybu|Ghybu]] Min ev guhartina xwe [https://ku.wiktionary.org/w/index.php?title=%D9%85%D8%B2%DA%AF%DB%95%D9%88%D8%AA&diff=prev&oldid=6337765] betal kir çunkî rast dibêjî ji bo hesabên biçûk dikare wekî reklam were fehmkirin, feqat bi min bila gotina te ya "peyv nayê dîtin" qaîde nebe, bila em li hemû madeyan yên Xjî zêde bikin, xisûsen ji nivîskarên me zêdekirina jêgirtinan bi min muhîm e. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:23, 22 tebax 2026 (UTC) == Etîmolojî (hevreh) == Li ser Wîkîferhengê etîmolojî pirr dirêj hatine nivîsandin û piranî jî ji hevrehê hatine tijî kirin. Hemû nivîsên ku tê de ne hewce nînin, bnr. {{q|ku|kirin#Etîmolojî}} nayê fêm kirin; hevreh li ser hatiye nivîsandin û tiştên ku hewce ne jî li bin hatine nivîsandin. Li ser en.wiki jî vitira nivîsandine: [[:en:kirin#Northern Kurdish]]. Herwiha li ser en.wiki hevrehan veşartine: [[:en:talk#Etymology 1]]. Bi zanîna min di nav ferhengan de etîmolojî bi du û sê hevokan tê nivîsandin. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 23:41, 22 tebax 2026 (UTC) :@[[Bikarhêner:Ghybu|Ghybu]] Tiştê herî pûç ew e wextê ku di etîmolojiya kurmancî de behsa zimanê tirkî dike ("eynî peyv ... wek ... ketiye tirkî jî"). [[Bikarhêner:Guherto|Guherto]] ([[Gotûbêja bikarhêner:Guherto|gotûbêj]]) 21:47, 27 tebax 2026 (UTC) == Heqên Interface admîntiyê == Merheba @[[Bikarhêner:Bikarhêner|Bikarhêner]], @[[Bikarhêner:Ghybu|Ghybu]], @[[Bikarhêner:Şêr|Şêr]], @[[Bikarhêner:Keyomerd|Keyomerd]], @[[Bikarhêner:Guherto|Guherto]], @[[Bikarhêner:Ferhengvan|Ferhengvan]], @[[Bikarhêner:Kurdanparez|Kurdanparez]] Ji bo guhartina rûpelên JS û CSSê heqên heqên [[:meta:Interface administrators|Interface Admin]] lazim e loma min li vir [[WF:Rêveber/Wikihez]] dengdanek çêkir. Ji kerema xwe dengê xwe bidin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:39, 30 tebax 2026 (UTC) smprvc3nnfn8yij9rwxpheoc42arcmd helawîk 0 1337925 6347203 6260348 2026-08-30T16:27:47Z Nenas nepênî 14450 Werger: +kurmancî : [[Helawîk]] (bi alîkarî) 6347203 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # [[Helawîk]]. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{g|ku|Helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|ku}}: {{W|ku|Helawîk}} * {{Z|tr}}: {{W-|tr|Un helvası}} {{werger-bin}} r3s84lx8e28xetyd91w0www49ct6kvl 6347205 6347203 2026-08-30T16:39:03Z Wikihez 7344 /* Werger */ Tenê ji bo zimanên din e (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347205 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # [[Helawîk]]. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{g|ku|Helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} ponc40jcqemauc7q6dux627srx1cxni 6347206 6347205 2026-08-30T16:39:41Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347206 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # {{e|ku|şîranî}} Cureyekî helaw ze. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{g|ku|Helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} qscu8o78gx6dyurxl77xxqoqqgc0ixe 6347207 6347206 2026-08-30T16:40:00Z Wikihez 7344 /* Navdêr */ 6347207 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # {{e|ku|şîranî}} [[cure|Cureyekî]] [[helaw]] e. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{g|ku|Helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} tvm86801p7246a8ublp3pvo5vaidnel 6347209 6347207 2026-08-30T16:43:32Z Wikihez 7344 /* Formên alternatîv */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347209 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=?}} # {{e|ku|şîranî}} [[cure|Cureyekî]] [[helaw]] e. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{alt|ku|helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} emvumw9j4pfhjo3rtlifaywb20b0kam 6347210 6347209 2026-08-30T16:44:02Z Wikihez 7344 /* Navdêr */ li gorî Nimûneyê (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347210 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # {{e|ku|şîranî}} [[cure|Cureyekî]] [[helaw]] e. #: {{mk|ku|Tama '''helawîkê''' gelekî xweşe}} ==== Formên alternatîv ==== * {{alt|ku|helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} i982gdiamwqyddqsocyby9l72uhdm35 6347273 6347210 2026-08-30T21:56:51Z Wikihez 7344 ([[m:Special:MyLanguage/User:Jon Harald Søby/diffedit|diffedit]]) 6347273 wikitext text/x-wiki == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Navdêr === {{navdêr|ku|z=m}} # {{e|ku|şîranî}} [[cure|Cureyekî]] [[helaw]] e. #: {{mk|ku|Tama '''helawîkê''' gelekî xweş e.}} ==== Formên alternatîv ==== * {{alt|ku|helawik}} ==== Etîmolojî ==== {{ji?|ku}} ==== Werger ==== {{werger-ser}} * {{Z|tr}}: {{W-|tr|un helvası}} {{werger-bin}} 0ti06vpyol7de01xtmmzyqueqpyzd7f Wîkîferheng:Xebat 4 1357857 6347299 6342887 2026-08-31T00:28:54Z Wikihez 7344 /* MediaWiki:Gadget-wikt.add-examples.js */ Bersiv 6347299 wikitext text/x-wiki {{/ser}} = Karên ferhengî = == Mane == * [[:Kategorî:Madeyên bê beşa mane]] ** [[:Kategorî:Madeyên bê beşa mane bi kurmancî]] Li ser van rûpelan ev made hene ku maneyan wan nehatine nivîsin û divê werin nivîsin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Etîmolojî == *[[:Kategorî:Daxwazên etîmolojiyê]] **[[:Kategorî:Daxwazên etîmolojiyê bi kurmancî]] Li ser van rûpelan ev made hene ku etîmolojiya wan hîn nehatine nivîsin. Ji bo alîkariyê binêre [[WF:Etîmolojî]] —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Cureyê rêzimanî == * [[:Kategorî:Gotarên bê kategoriya rêzimanî]] * [[:Kategorî:Gotarên bê kategoriya rêzimanî bi kurmancî]] Li ser van rûpelan ev made hene ku cureyên wan yên rêzimanî hîn nehatine nivîsin. Ji bo alîkariyê binêre [[Alîkarî:Cureyên peyvan]] —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Kontrol == * [[:Kategorî:Kontrol]] ** [[:Kategorî:Kontrola maneyê]] Ev madde bi botê hatine çêkirin, yek bi yek divê werin kontrolkirin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) = Şablon = == IPA == * {{ş|IPA}} divê [[Modul:IPA]] bi kar bîne. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Deng == Kurdîkirina belgekirina {{ş|deng}} lazim e.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:06, 19 tîrmeh 2026 (UTC) = Modul = == Modul:form of/templates == * [[Modul:form of/templates]]: Divê ev modul were rojanekirin û xeletiyên berê wekî ([[hevalê]]) werin rastkirin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:Merheba @[[Bikarhêner:Ghybu|Ghybu]] Te gotibû di vê modulê de xeletî hene, jkx tu dikarî li vir binivîsî çi kêmasî hene, daku wextê rojane dikim ez ji bîr nekim? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:16, 21 tîrmeh 2026 (UTC) *::Silav. Nizanim ji bîra min çûye... Herwiha ji bo çêkirina formên navdêran zanînên cîns û tîpa dawî bes e: *::* (-ê, mê) => çemandî, bangkirin *::* (-ê, nêr) => îzafe *::* (-ê, mê û nêr) => îzafe (nêr), bangkirin (mê), çemandî (mê) *::* (-a) => îzafe (mê) *::* (-ekî) => îzafe û çemandî (nêr, nebinavkirî) *::* (-eke) = > îzafe (mê, nebinavkirî) *::* ... *:: <code>if find(mw.title.getCurrentTitle().subpageText, 'ekî$') then ... end</code> *::<code><nowiki>{{ku-tewîn-navForm|<navdêr>|<zayend>}</nowiki></code> *::Tablo û nivîs di yekcarî de tên çêkirin... *::Feqet problem lêzêdekirina mînakan e. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 17:34, 21 tîrmeh 2026 (UTC) *:::Lêzêdekirina kîjan nimûneyan? Ev koda js ji bo çi ye? Qisûrê nenêre min fêm nekir :/ [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:13, 21 tîrmeh 2026 (UTC) *::::Li vira ([[hevalê#Formeke navdêrê]]) di bin maneyên 1. û 2. mînak nayên tevlî kirin :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 18:18, 21 tîrmeh 2026 (UTC) *:::::Ev tercîh e, ne mecbûrî ye, em dikarin [https://ku.wiktionary.org/w/index.php?title=heval%C3%AA&diff=prev&oldid=6276350 wisa] bikin. Wekî din? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:29, 21 tîrmeh 2026 (UTC) *::::::Min li jor tênê got ku tenê parametreyên "navdêr" û "zayend" hewce nee. Bi '''[//ku.wiktionary.org/w/index.php?title=heval%C3%AA&curid=969734&diff=6276353&oldid=6276350 vî]''' awayî jî tê çêkirin. Parametreyên din ne hewce ne. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 18:38, 21 tîrmeh 2026 (UTC) *:::::::Ji bo wê şabloneke din lazim e, bila ev şablon wekî îngilîzî bimîne em ji bo kurmancî yekî din çêkin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:42, 21 tîrmeh 2026 (UTC) *::::::::[https://ku.wiktionary.org/w/index.php?title=heval%C3%AA&oldid=6276885 wisa] çawa ye? Bi min nivîsîna nimûneyan zêde ne lazim e ji ber ku ti kes serê xwe pê naêşîne. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:46, 23 tîrmeh 2026 (UTC) *:::::::::@[[Bikarhêner:Ghybu|Ghybu]] Vê şablonê bi kar bînin an na? Navê şablonê kê çi be? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:07, 24 tîrmeh 2026 (UTC) == Modul:columns == * [[Modul:columns]] were rojanekirin û {{ş|kol3}} bila lînka ''nîşan bide'' deyne beriya sernavê, kolê di qutiya rengî de bila nebe. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Modul:etymon == * [[Modul:etymon kevn]]: Rojanekirin hewce ye. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == [[Modul:ziman/code to canonical name]] == Belgekirina skrîptê û js divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:31, 22 tîrmeh 2026 (UTC) :* [[MediaWiki:UpdateLanguageNameAndCode.js]] :[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:50, 22 tîrmeh 2026 (UTC) ::* [[Modul:ziman/print]] ::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:52, 22 tîrmeh 2026 (UTC) :::*[[Modul:ziman/şablon]] :::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:56, 22 tîrmeh 2026 (UTC) ::::* [[MediaWiki:Gadget-translation editor.js/ziman.json]] ::::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:06, 22 tîrmeh 2026 (UTC) == [[Modul:quote]] == Piştî ev modul hate hazirkirin, lazim e navên jegirtinan werin rastkirin û li hemûyan {{param|jêgirtin}} were zêdekirin. Bnr. [[Gotûbêja şablonê:Jêgirtin/Ehmedê Xanî/Mem û Zîn]] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:27, 5 tebax 2026 (UTC) ::Ev modul hema bêje hazir e. Hûn li ser van madeyan çi difikirin: # {{para|tarîx}} lazim e full date be eger na, lazim e {{para|sal}} were bikaranîn. Feqat "'''2021''' kanûna pêşîn 23" bi vî şiklî bi min ne problem e çnkî derdê en.wikt "attestation" e delîla herî pêşî jî sal e. #: {{demo|sep=wisa xuya dibe<br>|<nowiki>{{jêder-kitêb/ceribandin|en |tarîx=23 December 2021|nivîskar=Harry Hobbs; George Williams|sernav=Micronations and the Search for Sovereignty|url=https://www.cambridge.org/core/books/micronations-and-the-search-for-sovereignty/B0414A3A322695D9EE71E4CDDFDA06DE|weşanxane=Cambridge University Press|rûpel=155|isbn=978-1-009-15012-5|jêgirtin=jêgirtin.|t=-}}</nowiki>}} #{{para|amadekar}}/{{para|edîtor}}/{{para|terciman}} bi şiklê edîtoriya, amadekariya, tercimekirina #: {{demo|sep=dide<br>|<nowiki>{{jêder-kitêb/ceribandin|en |sernav=Medical Surgical Nursing|serî=Juta's Manual of Nursing|cildê-seriyê=volume 4|edîtor=Sophie Mataniele Mogotlane; Joyce Mokoena; Motshedisi Eunice Chauke; Anne Young|sal=2005|weşanxane=Juta Academic|isbn=978-0702171840|rûpel=!12-29|jêgirtin=jêgirtin|t=-}}</nowiki>}} --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:09, 10 tebax 2026 (UTC) :@[[Bikarhêner:Bikarhêner|Bikarhêner]] û @[[Bikarhêner:Ghybu|Ghybu]] Hîn gelek tişt hene divê îzah bikin û fikrê we pirs bikim, feqat îzahkirin pir zor e, em dest bi bikaranînê bikin û dûre tiştên ku hûn naxwazin em dikarin biguherînîn, dibe? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:11, 10 tebax 2026 (UTC) ::Dibe, piştî çêbû, em di praktîkê de bibînin ku çawa ye. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 18:05, 10 tebax 2026 (UTC) = Javascript = == [[Mediawiki:Gadget-citoid-helper.js]] == Ji bo bi citoidê kopîkirina malûmatên çavkaniyan amûreke wisa lazim e. Xisûsen ji ber ku bi çend amûrên din dikare were bikaranîn. Feqat çend problem hene, şablonên me de kêmasiya parametreyan gelek in û xerîteyên citoidê hîn nehatine çêkirin. Wana sererast bikin dûre vê amûrê çêkin, piştre [[MediaWiki:Gadget-start.js|start.js]] û [[MediaWiki:Gadget-wikt.add-examples.js|add examples.js]] were rojanekirin. - --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:04, 19 tîrmeh 2026 (UTC) :Merheba @[[Bikarhêner:Bikarhêner|Bikarhêner]], ez dibêjim karê Modul:quote zêde wext bistîne, bila em dest bi bikaranîna van amûran bikin dûre kêmasiyan em ê temam bikin înşela. Dikarî vana li cihên xwe yên rast kopî paste bikî? # [[Special:PermanentLink/6291574|Bikarhêner:Wikihez/skrîpt/js/Gadget-citoid-helper.js]] --> [[Mediawiki:Gadget-citoid-helper.js]] # Ya li jêr kopî bike qismê herî dawî ya AmûrênVeşartî li [[MediaWiki:Gadgets-definition]]: ## <code><nowiki>* citoid-helper[ResourceLoader|hidden|default|dependencies=mediawiki.util]|citoid-helper.js</nowiki></code> --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:58, 26 tîrmeh 2026 (UTC) == [[Mediawiki:Gadget-QQ.js]] == Ev amûr di şikle Minerva de. Her daîm vê xeletiyê dide: <syntaxhighlight lang="js"> TypeError: Cannot read properties of null (reading 'addEventListener') at css () at runScript () at Array.<anonymous> () at flushCssBuffer () </syntaxhighlight> [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:29, 18 tîrmeh 2026 (UTC) :* [[Bikarhêner:Wikihez/skrîpt/js/Gadget-QQ.js]] --> [[Mediawiki:Gadget-QQ.js]] :* [[Bikarhêner:Wikihez/Gadget-QQ.css]] --> [[Mediawiki:Gadget-QQ.css]] :Ez dibêjim çêbû lê ka çend roj biceribînim. Tiştên ku hatin sererastkirin: :# Google Books API Key dikarî zêde bikî, dixe cookies û di gerokê de dimîne. Berê bê API Key dixebitiya lê êdî mecbûr e ku API Key-a te hebe, bidestxistina wê ne zêde zor e lê dîsa jî tevlihev e. :# Êdî di mobîlê de dixebite, heta di mobîlê de xweştir xuya dike. :# Moda tarî :# OOUI dewsa jquery.ui :# Li qutiyê çi dixwazî zêde bikî, dikare li gorî îsm, sifet, fiîl bitewîne. Lê ji bo fiîl tenê dikare çend heb inflection bîne. :# Butona paqij bike lê zêde kir. :# Çend paqijiyên jêgirtinên Google Kitêbê niha hene. :[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:38, 18 tîrmeh 2026 (UTC) ::Tewandina fiîlan û xeletiya modulê lazim e were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:40, 21 tîrmeh 2026 (UTC) == [[MediaWiki:Gadget-wikt.add-examples.js]] == Min ev amûr hinek rojane kir feqat çend problem hene berî ku bar bikin. Tiştên ku min guhart: # Êdî li sayfeyên bi {{ş|maneid}} jî dixebite, # Cihê di wîkîtekstê de yê ku jêgirtin were îlawekirin baştir bû, # [[Mediawiki:Gadget-citoid-helper.js|citoid helper]] zêde kir ji bo ku bi hêsanî çavkanî bi riya doi, isbn an urlyê werin tijîkirin. * [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.css]] --> [[MediaWiki:Gadget-wikt.add-examples.css]] * [[Bikarhêner:Wikihez/Gadget-wikt.add-examples.js]] --> [[MediaWiki:Gadget-wikt.add-examples.js]] - --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:50, 19 tîrmeh 2026 (UTC) :Min "wikt." qismên cache kirinê ya wîkiya fransî bi [[MediaWiki:Gadget-StorageUtils.js]] guhartiye. loma ji bîr nekin wê amûrê li [[MediaWiki:Gadgets-definition]] zêde bikin. û navê amûrê jî biguhêrînin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:15, 23 tîrmeh 2026 (UTC) ::Berê li ser WF:ceribandin dixebitî. niha naxebite. Divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:10, 7 tebax 2026 (UTC) :::Muhîm e û zû were rastkirin feqat piştî îro ez çend rojan misaîd nebim: :::* Li şûna Navdêr 2, jêgirtin çû Navdêr 1 [https://ku.wiktionary.org/w/index.php?title=palas&diff=prev&oldid=6337440] :::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:01, 19 tebax 2026 (UTC) ::::{{çêbû}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:28, 31 tebax 2026 (UTC) == Gadget-translation editor == * [[MediaWiki:Gadget-translation editor.js]]: divê formata en.wîktê were bikaranîn ji ber ku me gelek tercime ji en.wîktê kopî kir û ev js hîn nikare formata wekî li jêr bi kar bîne. <syntaxhighlight lang="wikitext"> * {{Z|sh}}: *: Kirîlî: *: Latînî </syntaxhighlight> —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == [[Mediawiki:Gadget-linkify.js]] == * ''rûpeleke'' wekî<syntaxhighlight lang="wikitext">[[rûpeleke]]</syntaxhighlight> lînk dike, bi regexê belkî dikare wisa bike <syntaxhighlight lang="wikitext">[[rûpel]]eke</syntaxhighlight> —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) * Amûreke din wekî [[User:Wikihez/Gadget-linkify.js|linkify]] lazim e ku herfên mezin biçûk bike ji bo kurmancî.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) :{{r|Bikarhêner}} Merheba bira, dikarî viya jî bar bikî?: * [[Special:PermanentLink/6291974|linkify]] --> [[Mediawiki:Gadget-linkify.js]] Spas--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:42, 29 tîrmeh 2026 (UTC) :Dûre [https://ku.wiktionary.org/wiki/MediaWiki:Gadget-start.js#L-283 li vir] wiktviLinkify bike kuLinkify xêra xwe [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:51, 29 tîrmeh 2026 (UTC) ::Min ji bîr kir lê zêde bikim niha nikare "Dİ" bike "di", xeletiyeke berbelav a di nivîsên kurdî de, herfên din ên wekî ll yan rr jî hewce ne werin zêdekirin. Dûre em zêde bikin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:42, 29 tîrmeh 2026 (UTC) :::Min nû ferq kir, sayfeyên ku hîn nehatine çêkirin wîkîlînk nake. Problemeke mezin e divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:15, 30 tîrmeh 2026 (UTC) ::::Na, lînk dike, tiştekî din heye... [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 10:49, 31 tîrmeh 2026 (UTC) == Amûra manayê == Amûreke din ji bo nivîsina maneyê wekî Nimûne zêde bike lazim e [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/test.js&oldid=6276876 js] [https://ku.wiktionary.org/w/index.php?title=%C5%9Eablon:ceribandin2&oldid=6265629 şablon] [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/common.css&oldid=6265642 css] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:12, 23 tîrmeh 2026 (UTC) == [[MediaWiki:Gadget-jeder.js]] == @[[Bikarhêner:Ghybu|Ghybu]] Çavkaniyên jêderê di moda pêşdîtinê de jêderê vedişêre, ew jî min gelek eciz dike wextê çavkanî zêde dikim. Min ji Claude pirsî û kodan nîşanî wê da, wisa cewab da: Yes — and this file actually explains the whole thing precisely, better than my earlier guess about extract-stripping. What's happening: the CSS rule <syntaxhighlight lang="css"> .jeder{ display:none; } </syntaxhighlight> hides every citation by default, *unconditionally*. The only thing that ever makes it visible again is the gadget's JS: it finds each `.jeder`, builds the short "`— (year, author, +)`" summary from the `.j-pewist` fields, and either reveals the short version or — for citations with no `.j-pewist` fields — explicitly sets `display:inline` on the original. So visibility of citations depends entirely on this JS running. In the normal article view (Image 1) it runs, so you see the collapsed "`(1918, E. Rehmî Ji Mala Hekariyan, Amadekar: M. E. Bozarslan, +)`" form. In whatever generated Image 2 — a hover-preview/extract/API render — gadget JS doesn't execute, so nothing ever removes the `display:none`, and the citation vanishes completely rather than degrading to "still visible, just not collapsed." <b>The fix:</b> flip the default so the *un-collapsed* state is the safe fallback, and let JS do the hiding only after it successfully builds the short version. That way, any context without JS shows the full citation instead of nothing. CSS — remove the blanket hide: <syntaxhighlight lang="css"> .jeder { /* intentionally no display:none here — see Gadget-... .js */ } </syntaxhighlight> JS — do the hiding from script, after the short form exists: {{veşêre-ser}} <syntaxhighlight lang="js"> // Ji bo şablonên [[Şablon:jêder]] hatiye nivîsandin. // Parametreyên ku di navbera "<span class="j-pewist">...</span>" an "{{j-pêwîst|...}}" de ne venaşêre. $(function() { function nivisaKurtTevliBike(sund, nivisKurt) { var zede = $('<a>+</a>') .addClass('click') .attr('href', '#') .attr('title', 'zêdetir') .css('font-weight', 'bold'); var kurt = $(' <a>↩</a>') .addClass('click-kurt') .attr('href', '#') .attr('title', 'veşêre') .css('font-weight', 'bold'); $('<span>' + nivisKurt + '</span>') .append(zede).append(')') .addClass('jeder-kurt') .css('font-size', '0.85em') .insertAfter(sund); sund.append(' ').append(kurt); // Only hide the full citation once the short summary actually exists. // If this script never runs (no-JS clients, hover-preview extracts, // action=render, etc.), the full citation stays visible instead of // silently disappearing. sund.css('display', 'none'); } function vesere() { $('.jeder').each(function() { var elmTab = $(this).find('.j-pewist').clone(); if (elmTab.length) { var elm = ''; for (var i = elmTab.length - 1; i >= 0; i--) { elm = elmTab.eq(i).html() + ', ' + elm; } var nivisKurt = ' — (' + elm; nivisaKurtTevliBike($(this), nivisKurt); } // else: no j-pewist fields to shorten — leave the full citation // as it already renders (visible), nothing to do. }); } vesere(); $(".click").click(function(e) { e.preventDefault(); $(this).parent('.jeder-kurt').css('display', 'none'); $(this).parent('.jeder-kurt').prev().css('display', 'inline'); }); $(".click-kurt").click(function(e) { e.preventDefault(); $(this).parent('.jeder').css('display', 'none'); $(this).parent('.jeder').next().css('display', 'inline'); }); }); </syntaxhighlight> Net effect: - JS-enabled readers (normal article view): identical experience to today — collapsed short form with `+`/`↩` toggle. - No-JS contexts (previews, extracts, screen readers before JS loads, print, etc.): full citation is shown instead of nothing — a real regression fix rather than a cosmetic one. One caveat worth being upfront about: this fixes it *if* the preview context renders the gadget's HTML/CSS but doesn't execute gadget JS (which is the far more common case, and what this code strongly suggests is happening). If Image 2 instead comes from a pipeline that strips the `.jeder`/`.jegirtin-text` elements out of the HTML entirely before this CSS/JS even gets a chance to apply, no on-wiki CSS/JS change can help — that'd need the extract-generation config changed instead. Given what this gadget file shows, though, I'd bet on the CSS-hide explanation. {{veşêre-bin}} Em dûre biceribînin eger xeletî tinebe, vî tiştî jî rast bikin. --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:00, 23 tîrmeh 2026 (UTC) :Ez APIya MediaWiki rind nizanim belkî Claude dizane:) Em nikarin bibêjin dema ku moda "''action=edit''" e fonksiyona <code>function vesere()</code> bi kar meyîne. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 15:57, 24 tîrmeh 2026 (UTC) ::Na, di moda "edît"-ê de <code>var elmTab = null</code>... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:13, 24 tîrmeh 2026 (UTC) ?: <syntaxhighlight lang="js"> if ( mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit' ){ var elmTab = []; } else { var elmTab = $(this).find('.j-pewist').clone(); } </syntaxhighlight> --[[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:31, 24 tîrmeh 2026 (UTC) :Ez jî nizanim Claude çiqas ji mediawiki fêm dike lê heta niha ti tişt nîne ku min jê pirs kir û nikaribû çêke, bila wekî reklam nebe feqat Claude mikemmel e, dibêjim "li vir çima xeletiyeke wisa derdikeve" di dosyeya 2000 rêzî de diçe tiştê xelet tenê rast dike tiştekî din naguherîne. Chatgpt û aistudio qet wisa nakin, eynî dosyeyê deh cara dinivîsin, deh netîceyên cuda derdikevin :D :Em dikarin vê amûrê wextê edit û submitê neaktîv bikin wekî <syntaxhighlight lang="js">if (!(action === "edit" || action === "submit")) { :return;</syntaxhighlight> lê wê demê display:none wê çibe nizanim. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:23, 24 tîrmeh 2026 (UTC) ::display:none ne hewce ye ma jixwe di nav kodê [https://ku.wiktionary.org/w/index.php?title=MediaWiki:Gadget-jeder.js&oldid=6069025#L-49 L-49] de inline/none heye? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:53, 24 tîrmeh 2026 (UTC) :Min bi vî şiklî [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/vector-2022.js&diff=prev&oldid=6290816#L-28] ceriband feqat nexebitî. "display:none" di pêşdîtinê de dixebite feqat js naşixule. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:43, 25 tîrmeh 2026 (UTC) ::Kodên JSê pir hez nakim (pêşta hukurina APIya MWyê hewce bû) dîsa jî ez ê seh bikim :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:49, 27 tîrmeh 2026 (UTC) :::Ez niha bi vî şiklî [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/test.js&oldid=6290820] [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/common.css&oldid=6290821#L-8] bi kar tînim ti problem nîne. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:09, 27 tîrmeh 2026 (UTC) == [[MediaWiki:Gadget-PagePreviews.js]] == Ez dibêjim em vê amûrê jî çêkin [[:en:MediaWiki:Gadget-PagePreviews.js]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 10:56, 3 tebax 2026 (UTC) == [[MediaWiki:Gadget-start.js]] 2 == Tiştên ku werin zêdekirin: # Wextê ji Kategorî:Çavkanî şablonek zêde dikî, li gorî TemplateDatayê qutî çêke û malûmatên din werin nivîsîn. Jêgirtin bila bikeve nav şablonê. Niha dikeve nav jêderê ## Lêgerîn tenê navên Şablonan derdixe loma dîtina şablonekê belkî zor be, hemû beralîkirin werin data.jsonê were zêdekirin. # Dever/Şîve li gorî dataya modul:labels ji bo zimanan biguhêre niha hemû dibêje Behdînan :D # Autocomplete ji bo etîket û kategorî bi riya dataya modul:labels # Yekkirina qismên eleqedarî jegirtinan bi skrîpta nimûne zêde bike #Wextê |form=erê be |c=? li îsm û fiîlan zêde neke! [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 12:36, 21 tebax 2026 (UTC) = Moda tarî = == [[Şablon:wîkîpediya]] == Rengê tarî de xirab e.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:36, 4 tebax 2026 (UTC) = Bot = Karên ku bi botê werin çêkirin ji kerema xwe li vir binivîsin. == Kategorî:Biwêj == [[:Kategorî:Biwêj]] divê were paqijkirin, lîsteya madeyên {{ş|biwêj}} çêke, yên ku tê de bûn, kirin, man hene filtre bike yên din bi destî tê çêkirin.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Jêgirtin == Xistina jêgirtinên beşa [https://ku.wiktionary.org/w/index.php?search=insource%3A%2F%3D+*Ji+%5BWw%5D%C3%AAjey%C3%AA+*%3D%2F&title=Taybet%3AL%C3%AAger%C3%AEn&profile=advanced&fulltext=1&ns0=1&searchToken=8rh0bmw8dccsi7aynl6zli8uf ji wêjeyê] li beşa maneyê. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Bota Toolforgeê == Botekî Toolforgeê lazim e ji bo ku xeletiyên biçûk wekî şablonên bi navên îngilîzî werin kurdîkirin yan jî valahiya beşan rast bike û hwd.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) :Min [[Bikarhêner:Wikihez/skrîpt/py/kuwiktkozmetik.py|paqijiyen kozmetîk]] hazir kir feqat hîn navên şablonan naguhêre. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:05, 4 tebax 2026 (UTC) == Updatew == Bota [[Bikarhêner:Wikihez/skrîpt/py/updateW.py|updateW]] divê were rojanekirin. Yan jî yekî nû were çêkirin. Şablonên {{ş|W}} di beşa tercimeyan de sererast dike û zimanan rêz dike. Ya niha xeletiya navê zimanî dide.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == sihir --> sêhr == Tercimeyên ''[[sêhr]]'' hemû dibêje ''sihir'' loma bi botê lazim e kirin ''sêhr''. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:43, 18 tîrmeh 2026 (UTC) :Sihirbaz --> sêhrbaz [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:07, 18 tîrmeh 2026 (UTC) == Tercimeyên dîroknas == Li tercimeyên [[dîroknas]], hevmaneyên wê hewce ye were îlawekirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:44, 18 tîrmeh 2026 (UTC) oboe29lrwtmr2fee02fsrem87clrqdg 6347300 6347299 2026-08-31T00:29:07Z Wikihez 7344 [[MediaWiki:Gadget-aWa.js/belgekirin|aWa]]: Arşîvkirina 1 madeyê li [[Gotûbêja MediaWiki:Gadget-wikt.add-examples.js]] 6347300 wikitext text/x-wiki {{/ser}} = Karên ferhengî = == Mane == * [[:Kategorî:Madeyên bê beşa mane]] ** [[:Kategorî:Madeyên bê beşa mane bi kurmancî]] Li ser van rûpelan ev made hene ku maneyan wan nehatine nivîsin û divê werin nivîsin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Etîmolojî == *[[:Kategorî:Daxwazên etîmolojiyê]] **[[:Kategorî:Daxwazên etîmolojiyê bi kurmancî]] Li ser van rûpelan ev made hene ku etîmolojiya wan hîn nehatine nivîsin. Ji bo alîkariyê binêre [[WF:Etîmolojî]] —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Cureyê rêzimanî == * [[:Kategorî:Gotarên bê kategoriya rêzimanî]] * [[:Kategorî:Gotarên bê kategoriya rêzimanî bi kurmancî]] Li ser van rûpelan ev made hene ku cureyên wan yên rêzimanî hîn nehatine nivîsin. Ji bo alîkariyê binêre [[Alîkarî:Cureyên peyvan]] —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Kontrol == * [[:Kategorî:Kontrol]] ** [[:Kategorî:Kontrola maneyê]] Ev madde bi botê hatine çêkirin, yek bi yek divê werin kontrolkirin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) = Şablon = == IPA == * {{ş|IPA}} divê [[Modul:IPA]] bi kar bîne. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Deng == Kurdîkirina belgekirina {{ş|deng}} lazim e.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:06, 19 tîrmeh 2026 (UTC) = Modul = == Modul:form of/templates == * [[Modul:form of/templates]]: Divê ev modul were rojanekirin û xeletiyên berê wekî ([[hevalê]]) werin rastkirin. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:Merheba @[[Bikarhêner:Ghybu|Ghybu]] Te gotibû di vê modulê de xeletî hene, jkx tu dikarî li vir binivîsî çi kêmasî hene, daku wextê rojane dikim ez ji bîr nekim? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:16, 21 tîrmeh 2026 (UTC) *::Silav. Nizanim ji bîra min çûye... Herwiha ji bo çêkirina formên navdêran zanînên cîns û tîpa dawî bes e: *::* (-ê, mê) => çemandî, bangkirin *::* (-ê, nêr) => îzafe *::* (-ê, mê û nêr) => îzafe (nêr), bangkirin (mê), çemandî (mê) *::* (-a) => îzafe (mê) *::* (-ekî) => îzafe û çemandî (nêr, nebinavkirî) *::* (-eke) = > îzafe (mê, nebinavkirî) *::* ... *:: <code>if find(mw.title.getCurrentTitle().subpageText, 'ekî$') then ... end</code> *::<code><nowiki>{{ku-tewîn-navForm|<navdêr>|<zayend>}</nowiki></code> *::Tablo û nivîs di yekcarî de tên çêkirin... *::Feqet problem lêzêdekirina mînakan e. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 17:34, 21 tîrmeh 2026 (UTC) *:::Lêzêdekirina kîjan nimûneyan? Ev koda js ji bo çi ye? Qisûrê nenêre min fêm nekir :/ [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:13, 21 tîrmeh 2026 (UTC) *::::Li vira ([[hevalê#Formeke navdêrê]]) di bin maneyên 1. û 2. mînak nayên tevlî kirin :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 18:18, 21 tîrmeh 2026 (UTC) *:::::Ev tercîh e, ne mecbûrî ye, em dikarin [https://ku.wiktionary.org/w/index.php?title=heval%C3%AA&diff=prev&oldid=6276350 wisa] bikin. Wekî din? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:29, 21 tîrmeh 2026 (UTC) *::::::Min li jor tênê got ku tenê parametreyên "navdêr" û "zayend" hewce nee. Bi '''[//ku.wiktionary.org/w/index.php?title=heval%C3%AA&curid=969734&diff=6276353&oldid=6276350 vî]''' awayî jî tê çêkirin. Parametreyên din ne hewce ne. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 18:38, 21 tîrmeh 2026 (UTC) *:::::::Ji bo wê şabloneke din lazim e, bila ev şablon wekî îngilîzî bimîne em ji bo kurmancî yekî din çêkin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:42, 21 tîrmeh 2026 (UTC) *::::::::[https://ku.wiktionary.org/w/index.php?title=heval%C3%AA&oldid=6276885 wisa] çawa ye? Bi min nivîsîna nimûneyan zêde ne lazim e ji ber ku ti kes serê xwe pê naêşîne. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:46, 23 tîrmeh 2026 (UTC) *:::::::::@[[Bikarhêner:Ghybu|Ghybu]] Vê şablonê bi kar bînin an na? Navê şablonê kê çi be? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:07, 24 tîrmeh 2026 (UTC) == Modul:columns == * [[Modul:columns]] were rojanekirin û {{ş|kol3}} bila lînka ''nîşan bide'' deyne beriya sernavê, kolê di qutiya rengî de bila nebe. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Modul:etymon == * [[Modul:etymon kevn]]: Rojanekirin hewce ye. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == [[Modul:ziman/code to canonical name]] == Belgekirina skrîptê û js divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:31, 22 tîrmeh 2026 (UTC) :* [[MediaWiki:UpdateLanguageNameAndCode.js]] :[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:50, 22 tîrmeh 2026 (UTC) ::* [[Modul:ziman/print]] ::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:52, 22 tîrmeh 2026 (UTC) :::*[[Modul:ziman/şablon]] :::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:56, 22 tîrmeh 2026 (UTC) ::::* [[MediaWiki:Gadget-translation editor.js/ziman.json]] ::::[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:06, 22 tîrmeh 2026 (UTC) == [[Modul:quote]] == Piştî ev modul hate hazirkirin, lazim e navên jegirtinan werin rastkirin û li hemûyan {{param|jêgirtin}} were zêdekirin. Bnr. [[Gotûbêja şablonê:Jêgirtin/Ehmedê Xanî/Mem û Zîn]] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:27, 5 tebax 2026 (UTC) ::Ev modul hema bêje hazir e. Hûn li ser van madeyan çi difikirin: # {{para|tarîx}} lazim e full date be eger na, lazim e {{para|sal}} were bikaranîn. Feqat "'''2021''' kanûna pêşîn 23" bi vî şiklî bi min ne problem e çnkî derdê en.wikt "attestation" e delîla herî pêşî jî sal e. #: {{demo|sep=wisa xuya dibe<br>|<nowiki>{{jêder-kitêb/ceribandin|en |tarîx=23 December 2021|nivîskar=Harry Hobbs; George Williams|sernav=Micronations and the Search for Sovereignty|url=https://www.cambridge.org/core/books/micronations-and-the-search-for-sovereignty/B0414A3A322695D9EE71E4CDDFDA06DE|weşanxane=Cambridge University Press|rûpel=155|isbn=978-1-009-15012-5|jêgirtin=jêgirtin.|t=-}}</nowiki>}} #{{para|amadekar}}/{{para|edîtor}}/{{para|terciman}} bi şiklê edîtoriya, amadekariya, tercimekirina #: {{demo|sep=dide<br>|<nowiki>{{jêder-kitêb/ceribandin|en |sernav=Medical Surgical Nursing|serî=Juta's Manual of Nursing|cildê-seriyê=volume 4|edîtor=Sophie Mataniele Mogotlane; Joyce Mokoena; Motshedisi Eunice Chauke; Anne Young|sal=2005|weşanxane=Juta Academic|isbn=978-0702171840|rûpel=!12-29|jêgirtin=jêgirtin|t=-}}</nowiki>}} --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:09, 10 tebax 2026 (UTC) :@[[Bikarhêner:Bikarhêner|Bikarhêner]] û @[[Bikarhêner:Ghybu|Ghybu]] Hîn gelek tişt hene divê îzah bikin û fikrê we pirs bikim, feqat îzahkirin pir zor e, em dest bi bikaranînê bikin û dûre tiştên ku hûn naxwazin em dikarin biguherînîn, dibe? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 13:11, 10 tebax 2026 (UTC) ::Dibe, piştî çêbû, em di praktîkê de bibînin ku çawa ye. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 18:05, 10 tebax 2026 (UTC) = Javascript = == [[Mediawiki:Gadget-citoid-helper.js]] == Ji bo bi citoidê kopîkirina malûmatên çavkaniyan amûreke wisa lazim e. Xisûsen ji ber ku bi çend amûrên din dikare were bikaranîn. Feqat çend problem hene, şablonên me de kêmasiya parametreyan gelek in û xerîteyên citoidê hîn nehatine çêkirin. Wana sererast bikin dûre vê amûrê çêkin, piştre [[MediaWiki:Gadget-start.js|start.js]] û [[MediaWiki:Gadget-wikt.add-examples.js|add examples.js]] were rojanekirin. - --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:04, 19 tîrmeh 2026 (UTC) :Merheba @[[Bikarhêner:Bikarhêner|Bikarhêner]], ez dibêjim karê Modul:quote zêde wext bistîne, bila em dest bi bikaranîna van amûran bikin dûre kêmasiyan em ê temam bikin înşela. Dikarî vana li cihên xwe yên rast kopî paste bikî? # [[Special:PermanentLink/6291574|Bikarhêner:Wikihez/skrîpt/js/Gadget-citoid-helper.js]] --> [[Mediawiki:Gadget-citoid-helper.js]] # Ya li jêr kopî bike qismê herî dawî ya AmûrênVeşartî li [[MediaWiki:Gadgets-definition]]: ## <code><nowiki>* citoid-helper[ResourceLoader|hidden|default|dependencies=mediawiki.util]|citoid-helper.js</nowiki></code> --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:58, 26 tîrmeh 2026 (UTC) == [[Mediawiki:Gadget-QQ.js]] == Ev amûr di şikle Minerva de. Her daîm vê xeletiyê dide: <syntaxhighlight lang="js"> TypeError: Cannot read properties of null (reading 'addEventListener') at css () at runScript () at Array.<anonymous> () at flushCssBuffer () </syntaxhighlight> [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:29, 18 tîrmeh 2026 (UTC) :* [[Bikarhêner:Wikihez/skrîpt/js/Gadget-QQ.js]] --> [[Mediawiki:Gadget-QQ.js]] :* [[Bikarhêner:Wikihez/Gadget-QQ.css]] --> [[Mediawiki:Gadget-QQ.css]] :Ez dibêjim çêbû lê ka çend roj biceribînim. Tiştên ku hatin sererastkirin: :# Google Books API Key dikarî zêde bikî, dixe cookies û di gerokê de dimîne. Berê bê API Key dixebitiya lê êdî mecbûr e ku API Key-a te hebe, bidestxistina wê ne zêde zor e lê dîsa jî tevlihev e. :# Êdî di mobîlê de dixebite, heta di mobîlê de xweştir xuya dike. :# Moda tarî :# OOUI dewsa jquery.ui :# Li qutiyê çi dixwazî zêde bikî, dikare li gorî îsm, sifet, fiîl bitewîne. Lê ji bo fiîl tenê dikare çend heb inflection bîne. :# Butona paqij bike lê zêde kir. :# Çend paqijiyên jêgirtinên Google Kitêbê niha hene. :[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:38, 18 tîrmeh 2026 (UTC) ::Tewandina fiîlan û xeletiya modulê lazim e were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:40, 21 tîrmeh 2026 (UTC) == Gadget-translation editor == * [[MediaWiki:Gadget-translation editor.js]]: divê formata en.wîktê were bikaranîn ji ber ku me gelek tercime ji en.wîktê kopî kir û ev js hîn nikare formata wekî li jêr bi kar bîne. <syntaxhighlight lang="wikitext"> * {{Z|sh}}: *: Kirîlî: *: Latînî </syntaxhighlight> —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == [[Mediawiki:Gadget-linkify.js]] == * ''rûpeleke'' wekî<syntaxhighlight lang="wikitext">[[rûpeleke]]</syntaxhighlight> lînk dike, bi regexê belkî dikare wisa bike <syntaxhighlight lang="wikitext">[[rûpel]]eke</syntaxhighlight> —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) * Amûreke din wekî [[User:Wikihez/Gadget-linkify.js|linkify]] lazim e ku herfên mezin biçûk bike ji bo kurmancî.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) :{{r|Bikarhêner}} Merheba bira, dikarî viya jî bar bikî?: * [[Special:PermanentLink/6291974|linkify]] --> [[Mediawiki:Gadget-linkify.js]] Spas--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:42, 29 tîrmeh 2026 (UTC) :Dûre [https://ku.wiktionary.org/wiki/MediaWiki:Gadget-start.js#L-283 li vir] wiktviLinkify bike kuLinkify xêra xwe [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 11:51, 29 tîrmeh 2026 (UTC) ::Min ji bîr kir lê zêde bikim niha nikare "Dİ" bike "di", xeletiyeke berbelav a di nivîsên kurdî de, herfên din ên wekî ll yan rr jî hewce ne werin zêdekirin. Dûre em zêde bikin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:42, 29 tîrmeh 2026 (UTC) :::Min nû ferq kir, sayfeyên ku hîn nehatine çêkirin wîkîlînk nake. Problemeke mezin e divê were rastkirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:15, 30 tîrmeh 2026 (UTC) ::::Na, lînk dike, tiştekî din heye... [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 10:49, 31 tîrmeh 2026 (UTC) == Amûra manayê == Amûreke din ji bo nivîsina maneyê wekî Nimûne zêde bike lazim e [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/test.js&oldid=6276876 js] [https://ku.wiktionary.org/w/index.php?title=%C5%9Eablon:ceribandin2&oldid=6265629 şablon] [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/common.css&oldid=6265642 css] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:12, 23 tîrmeh 2026 (UTC) == [[MediaWiki:Gadget-jeder.js]] == @[[Bikarhêner:Ghybu|Ghybu]] Çavkaniyên jêderê di moda pêşdîtinê de jêderê vedişêre, ew jî min gelek eciz dike wextê çavkanî zêde dikim. Min ji Claude pirsî û kodan nîşanî wê da, wisa cewab da: Yes — and this file actually explains the whole thing precisely, better than my earlier guess about extract-stripping. What's happening: the CSS rule <syntaxhighlight lang="css"> .jeder{ display:none; } </syntaxhighlight> hides every citation by default, *unconditionally*. The only thing that ever makes it visible again is the gadget's JS: it finds each `.jeder`, builds the short "`— (year, author, +)`" summary from the `.j-pewist` fields, and either reveals the short version or — for citations with no `.j-pewist` fields — explicitly sets `display:inline` on the original. So visibility of citations depends entirely on this JS running. In the normal article view (Image 1) it runs, so you see the collapsed "`(1918, E. Rehmî Ji Mala Hekariyan, Amadekar: M. E. Bozarslan, +)`" form. In whatever generated Image 2 — a hover-preview/extract/API render — gadget JS doesn't execute, so nothing ever removes the `display:none`, and the citation vanishes completely rather than degrading to "still visible, just not collapsed." <b>The fix:</b> flip the default so the *un-collapsed* state is the safe fallback, and let JS do the hiding only after it successfully builds the short version. That way, any context without JS shows the full citation instead of nothing. CSS — remove the blanket hide: <syntaxhighlight lang="css"> .jeder { /* intentionally no display:none here — see Gadget-... .js */ } </syntaxhighlight> JS — do the hiding from script, after the short form exists: {{veşêre-ser}} <syntaxhighlight lang="js"> // Ji bo şablonên [[Şablon:jêder]] hatiye nivîsandin. // Parametreyên ku di navbera "<span class="j-pewist">...</span>" an "{{j-pêwîst|...}}" de ne venaşêre. $(function() { function nivisaKurtTevliBike(sund, nivisKurt) { var zede = $('<a>+</a>') .addClass('click') .attr('href', '#') .attr('title', 'zêdetir') .css('font-weight', 'bold'); var kurt = $(' <a>↩</a>') .addClass('click-kurt') .attr('href', '#') .attr('title', 'veşêre') .css('font-weight', 'bold'); $('<span>' + nivisKurt + '</span>') .append(zede).append(')') .addClass('jeder-kurt') .css('font-size', '0.85em') .insertAfter(sund); sund.append(' ').append(kurt); // Only hide the full citation once the short summary actually exists. // If this script never runs (no-JS clients, hover-preview extracts, // action=render, etc.), the full citation stays visible instead of // silently disappearing. sund.css('display', 'none'); } function vesere() { $('.jeder').each(function() { var elmTab = $(this).find('.j-pewist').clone(); if (elmTab.length) { var elm = ''; for (var i = elmTab.length - 1; i >= 0; i--) { elm = elmTab.eq(i).html() + ', ' + elm; } var nivisKurt = ' — (' + elm; nivisaKurtTevliBike($(this), nivisKurt); } // else: no j-pewist fields to shorten — leave the full citation // as it already renders (visible), nothing to do. }); } vesere(); $(".click").click(function(e) { e.preventDefault(); $(this).parent('.jeder-kurt').css('display', 'none'); $(this).parent('.jeder-kurt').prev().css('display', 'inline'); }); $(".click-kurt").click(function(e) { e.preventDefault(); $(this).parent('.jeder').css('display', 'none'); $(this).parent('.jeder').next().css('display', 'inline'); }); }); </syntaxhighlight> Net effect: - JS-enabled readers (normal article view): identical experience to today — collapsed short form with `+`/`↩` toggle. - No-JS contexts (previews, extracts, screen readers before JS loads, print, etc.): full citation is shown instead of nothing — a real regression fix rather than a cosmetic one. One caveat worth being upfront about: this fixes it *if* the preview context renders the gadget's HTML/CSS but doesn't execute gadget JS (which is the far more common case, and what this code strongly suggests is happening). If Image 2 instead comes from a pipeline that strips the `.jeder`/`.jegirtin-text` elements out of the HTML entirely before this CSS/JS even gets a chance to apply, no on-wiki CSS/JS change can help — that'd need the extract-generation config changed instead. Given what this gadget file shows, though, I'd bet on the CSS-hide explanation. {{veşêre-bin}} Em dûre biceribînin eger xeletî tinebe, vî tiştî jî rast bikin. --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:00, 23 tîrmeh 2026 (UTC) :Ez APIya MediaWiki rind nizanim belkî Claude dizane:) Em nikarin bibêjin dema ku moda "''action=edit''" e fonksiyona <code>function vesere()</code> bi kar meyîne. [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 15:57, 24 tîrmeh 2026 (UTC) ::Na, di moda "edît"-ê de <code>var elmTab = null</code>... [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:13, 24 tîrmeh 2026 (UTC) ?: <syntaxhighlight lang="js"> if ( mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit' ){ var elmTab = []; } else { var elmTab = $(this).find('.j-pewist').clone(); } </syntaxhighlight> --[[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:31, 24 tîrmeh 2026 (UTC) :Ez jî nizanim Claude çiqas ji mediawiki fêm dike lê heta niha ti tişt nîne ku min jê pirs kir û nikaribû çêke, bila wekî reklam nebe feqat Claude mikemmel e, dibêjim "li vir çima xeletiyeke wisa derdikeve" di dosyeya 2000 rêzî de diçe tiştê xelet tenê rast dike tiştekî din naguherîne. Chatgpt û aistudio qet wisa nakin, eynî dosyeyê deh cara dinivîsin, deh netîceyên cuda derdikevin :D :Em dikarin vê amûrê wextê edit û submitê neaktîv bikin wekî <syntaxhighlight lang="js">if (!(action === "edit" || action === "submit")) { :return;</syntaxhighlight> lê wê demê display:none wê çibe nizanim. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:23, 24 tîrmeh 2026 (UTC) ::display:none ne hewce ye ma jixwe di nav kodê [https://ku.wiktionary.org/w/index.php?title=MediaWiki:Gadget-jeder.js&oldid=6069025#L-49 L-49] de inline/none heye? [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:53, 24 tîrmeh 2026 (UTC) :Min bi vî şiklî [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/vector-2022.js&diff=prev&oldid=6290816#L-28] ceriband feqat nexebitî. "display:none" di pêşdîtinê de dixebite feqat js naşixule. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:43, 25 tîrmeh 2026 (UTC) ::Kodên JSê pir hez nakim (pêşta hukurina APIya MWyê hewce bû) dîsa jî ez ê seh bikim :) [[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 16:49, 27 tîrmeh 2026 (UTC) :::Ez niha bi vî şiklî [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/test.js&oldid=6290820] [https://ku.wiktionary.org/w/index.php?title=Bikarh%C3%AAner:Wikihez/common.css&oldid=6290821#L-8] bi kar tînim ti problem nîne. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:09, 27 tîrmeh 2026 (UTC) == [[MediaWiki:Gadget-PagePreviews.js]] == Ez dibêjim em vê amûrê jî çêkin [[:en:MediaWiki:Gadget-PagePreviews.js]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 10:56, 3 tebax 2026 (UTC) == [[MediaWiki:Gadget-start.js]] 2 == Tiştên ku werin zêdekirin: # Wextê ji Kategorî:Çavkanî şablonek zêde dikî, li gorî TemplateDatayê qutî çêke û malûmatên din werin nivîsîn. Jêgirtin bila bikeve nav şablonê. Niha dikeve nav jêderê ## Lêgerîn tenê navên Şablonan derdixe loma dîtina şablonekê belkî zor be, hemû beralîkirin werin data.jsonê were zêdekirin. # Dever/Şîve li gorî dataya modul:labels ji bo zimanan biguhêre niha hemû dibêje Behdînan :D # Autocomplete ji bo etîket û kategorî bi riya dataya modul:labels # Yekkirina qismên eleqedarî jegirtinan bi skrîpta nimûne zêde bike #Wextê |form=erê be |c=? li îsm û fiîlan zêde neke! [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 12:36, 21 tebax 2026 (UTC) = Moda tarî = == [[Şablon:wîkîpediya]] == Rengê tarî de xirab e.--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:36, 4 tebax 2026 (UTC) = Bot = Karên ku bi botê werin çêkirin ji kerema xwe li vir binivîsin. == Kategorî:Biwêj == [[:Kategorî:Biwêj]] divê were paqijkirin, lîsteya madeyên {{ş|biwêj}} çêke, yên ku tê de bûn, kirin, man hene filtre bike yên din bi destî tê çêkirin.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Jêgirtin == Xistina jêgirtinên beşa [https://ku.wiktionary.org/w/index.php?search=insource%3A%2F%3D+*Ji+%5BWw%5D%C3%AAjey%C3%AA+*%3D%2F&title=Taybet%3AL%C3%AAger%C3%AEn&profile=advanced&fulltext=1&ns0=1&searchToken=8rh0bmw8dccsi7aynl6zli8uf ji wêjeyê] li beşa maneyê. —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == Bota Toolforgeê == Botekî Toolforgeê lazim e ji bo ku xeletiyên biçûk wekî şablonên bi navên îngilîzî werin kurdîkirin yan jî valahiya beşan rast bike û hwd.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) :Min [[Bikarhêner:Wikihez/skrîpt/py/kuwiktkozmetik.py|paqijiyen kozmetîk]] hazir kir feqat hîn navên şablonan naguhêre. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:05, 4 tebax 2026 (UTC) == Updatew == Bota [[Bikarhêner:Wikihez/skrîpt/py/updateW.py|updateW]] divê were rojanekirin. Yan jî yekî nû were çêkirin. Şablonên {{ş|W}} di beşa tercimeyan de sererast dike û zimanan rêz dike. Ya niha xeletiya navê zimanî dide.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) == sihir --> sêhr == Tercimeyên ''[[sêhr]]'' hemû dibêje ''sihir'' loma bi botê lazim e kirin ''sêhr''. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:43, 18 tîrmeh 2026 (UTC) :Sihirbaz --> sêhrbaz [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:07, 18 tîrmeh 2026 (UTC) == Tercimeyên dîroknas == Li tercimeyên [[dîroknas]], hevmaneyên wê hewce ye were îlawekirin. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:44, 18 tîrmeh 2026 (UTC) t8iwif2udu1bnue8lhrmbxvsau2ucpm Bikarhêner:Wikihez/ceribandin 2 1357863 6347282 6323376 2026-08-30T22:45:35Z Wikihez 7344 6347282 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Maneya 1ê. #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} mrbvm4x1uprjqcq2eeiawgqgt4ksmkr 6347283 6347282 2026-08-30T22:45:56Z Wikihez 7344 guhertina maneyê (DefSideBoxes) 6347283 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} bm3lv8vl2hzuqtfzky5xe465f3d0lvq 6347284 6347283 2026-08-30T22:46:35Z Wikihez 7344 +Hevmane (DefSideBoxes) 6347284 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} mgi0gjiao3wp4bec0ftasjh3gqjeqv8 6347285 6347284 2026-08-30T22:47:07Z Wikihez 7344 +Herwiha binêre (DefSideBoxes) 6347285 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} kndseyhepk3zu0sai6512gzt5a37gnb 6347286 6347285 2026-08-30T23:17:50Z Wikihez 7344 +Etîket (DefSideBoxes) 6347286 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{e|ku|etîket}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} kdqoon1da1lrfh5ca0fjzia1xgfy58z 6347287 6347286 2026-08-30T23:18:29Z Wikihez 7344 +Etîket (DefSideBoxes) 6347287 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{e|ku|etîket|etîket2}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} rd0gn0gbhf1jke2usyc377eyu60ulor 6347288 6347287 2026-08-30T23:19:31Z Wikihez 7344 +Hevmane (DefSideBoxes) 6347288 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{e|ku|etîket|etîket2}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} lwb6ifzfd0muu2dhqulm8qvz3a864bl 6347289 6347288 2026-08-30T23:22:50Z Wikihez 7344 +nasnav (DefSideBoxes) 6347289 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} ozfa8mz846kahm5dnr9f56dx5becw57 6347290 6347289 2026-08-30T23:23:15Z Wikihez 7344 +Kategorî (DefSideBoxes) 6347290 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} 8xgy5gwc7tudtmhbey3tekl9bxey0hw 6347292 6347290 2026-08-30T23:33:59Z Wikihez 7344 +Etîket (DefSideBoxes) 6347292 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Bikaranîn ==== ''Çend not li ser bikaranîna peyvê.'' ==== Jê ==== {{kol3|ku|cure=Jê |ceribandinvan }} ==== Têkildar ==== * ''Peyvên ku têkiliya [[etîmolojîk]] bi peyvê re hene''. ==== Herwiha binêre ==== {{kol3|ku|cure=Herwiha binêre |test }} === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} j9b00yxr4lojzymrspc2mzgszk9ajj4 6347306 6347292 2026-08-31T00:36:34Z Wikihez 7344 /* Lêker */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347306 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # Mane xweş e #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} rnppgg1njy069x6mb60kvjf49xb1et6 6347309 6347306 2026-08-31T00:42:22Z Wikihez 7344 /* Lêker */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347309 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # {{mane?|ku}} #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} arpviqtmr8noa2bb96xpnso9e1c1egj 6347310 6347309 2026-08-31T00:42:33Z Wikihez 7344 guhertina maneyê (DefSideBoxes) 6347310 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # {{mane?|ku}} test mane #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} n6ysxuuifqtj7sz05mhue0u04y0yumq 6347311 6347310 2026-08-31T00:42:50Z Wikihez 7344 /* Lêker */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347311 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # {{mane?|ku}} #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} arpviqtmr8noa2bb96xpnso9e1c1egj 6347314 6347311 2026-08-31T00:54:50Z Wikihez 7344 guhertina maneyê (DefSideBoxes) 6347314 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # [[test|test]] #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} 0gxgoyv4kgkhafangyf4323vddcndh0 6347315 6347314 2026-08-31T00:55:09Z Wikihez 7344 +Hevmane (DefSideBoxes) 6347315 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # [[test|test]] #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>|teste}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} rfmerdibkpav1sxek5u3ug6zkpu08d9 6347322 6347315 2026-08-31T09:06:42Z Wikihez 7344 +Têkildar (DefSideBoxes) 6347322 wikitext text/x-wiki {{/vê rêzê neguhêre}} == {{ziman|ku}} == === Bilêvkirin === * {{ku-IPA}} * {{ku-kîte}} === Lêker === [[Wêne:Example.jpg|thumb|Mînak]] {{lêker|ku|c=h-gh}} # [[test|test]] #: {{hevmane|ku|hevmane<t:îzah><c:m>|hevmane2<c:n>|teste}} #: {{mk|ku|'''Nimûneyeke''' bikaranînê ya vê peyvê.}} #* {{bênimûne|ku}} # {{e|ku|Dihok}} {{f|ku|mecazî}} Maneya 2an. #* {{jêder-pirtûk|ku|jêgirtin=Jêgirtinek ji kitêbekê.|nivîskar=Rojen Barnas|sernav=Sîlvan/ Silîvan / FARQÎN|sal=2013|weşandxane=Nûbihar|rûpel=189|isbn= 9786055402884, 6055402882}} # {{maneid|ku|id}} {{K|ku|kat}} {{e|ku|etîket|etîket2}} Maneya 3an. ==== Formên alternatîv ==== {{stûn| * [[zar vekirin]] * [[zahr vekirin]] * [[zahrî vekirin]] * [[zehr vekirin]] * [[zehrî vekirin]] * [[zarve kirin]] * [[zarîve kirin]] * [[zahrve kirin]] * [[zahrîve kirin]] * [[zehrve kirin]] * [[zehrîvekirin]] * [[zarvekirin]] * [[zarîvekirin]] * [[zahrvekirin]] * [[zahrîvekirin]] * [[zehrvekirin]] * [[zehrîvekirin]] }} ==== Hevmane ==== * [[lasayî kirin]] ==== Jê ==== * [[zarîker]] * [[zarîkirî]] * [[zarveker]] ==== Têkildar ==== {{kol3|ku|cure=Têkildar |test<q:tt> }} ==== Etîmolojî ==== Ji {{heve|ku|[[zar]]î|kirin}}. === Etîmolojî === ''Çîroka tarîxî ya eslê kelîmeyê. Nimûneya bandor'': Ji {{deyn|ota|ku|باندره}}, {{q|ota|باكدیره}}, ({{hv|tr|bandıra}}) ji {{ji|vec|ku|bandéra}} ({{hv|it|bandiera}}) ji {{ji|gem|ku}} *''bandwa-'' ({{cotreh|ku|band|bend}}). Bide ber {{hv|fr|bandière}} (wek {{hv|en|banner}}), {{hv|el|παντιέρα}}. ==== Binêre herwiha ==== * ''Peyvên eleqadar lê belê têkiliya etîmolojîk nîne''. * {{wpedî}} ==== Werger ==== {{werger-ser|1|Maneya 1ê}} * {{Z|en}}: {{W+|en|word}} {{werger-bin}} {{werger-ser|2|Maneya an}} {{werger-bin}} {{werger-bnr|Maneya 3an|kelîme}} === Navdêr === {{ku-tewîn-nav|nav=nimûne|mê}} {{navdêr|ku|z=m}} # mane 1 #: mînak 1-1 #: mînak 1-2 #* jêgirtin 1-1 #* jêgirtin 1-2 # mane 2 #: mînak 2-1 #: mînak 2-2 #* jêgirtin 2-1 #* jêgirtin 2-2 # mane 3 ==== Werger ==== {{werger-ser|1|Maneya 1ê}} {{werger-bin}} {{werger-ser|2|Maneya 2an}} {{werger-bin}} {{werger-ser|3|Maneya 3an}} {{werger-bin}} === Çavkanî === {{Çavkanî}} * Çavkaniyên din li vir binivîse. ==== Modul:zimanên etîmolojiyê==== {{Special:PrefixIndex/Modul:zimanên etîmolojiyê/|stripprefix=yes}} ==== Modul:etymology languages==== {{Special:PrefixIndex/Modul:etymology languages/|stripprefix=yes}} ==== Binêre herwiha ==== {{veşêre-ser}} {| class="wikitable" !wikilink |- |[[Pêvek:Bêçavkanî]] |- |[[Pêvek:Bêçavkanî/a]] |- |[[Pêvek:Bêçavkanî/a/alozbûn wekî wayra]] |- |[[Pêvek:Bêçavkanî/aloq]] |- |[[Pêvek:Bêçavkanî/alozbûn]] |- |[[Pêvek:Bêçavkanî/amerzandin]] |- |[[Pêvek:Bêçavkanî/asûm]] |- |[[Pêvek:Bêçavkanî/bester]] |- |[[Pêvek:Bêçavkanî/cewser]] |- |[[Pêvek:Bêçavkanî/derbest]] |- |[[Pêvek:Bêçavkanî/dogirme]] |- |[[Pêvek:Bêçavkanî/dolivandin]] |- |[[Pêvek:Bêçavkanî/dêziman]] |- |[[Pêvek:Bêçavkanî/girêmestî]] |- |[[Pêvek:Bêçavkanî/hesoskî]] |- |[[Pêvek:Bêçavkanî/hilinder]] |- |[[Pêvek:Bêçavkanî/ji barê ve]] |- |[[Pêvek:Bêçavkanî/kakilîk]] |- |[[Pêvek:Bêçavkanî/kedpîr]] |- |[[Pêvek:Bêçavkanî/kilûç]] |- |[[Pêvek:Bêçavkanî/nêremê]] |- |[[Pêvek:Bêçavkanî/nû]] |- |[[Pêvek:Bêçavkanî/oc bûn]] |- |[[Pêvek:Bêçavkanî/qomik]] |- |[[Pêvek:Bêçavkanî/rojol]] |- |[[Pêvek:Bêçavkanî/sîniyar]] |- |[[Pêvek:Bêçavkanî/tazîger]] |- |[[Pêvek:Bêçavkanî/tevilîn]] |- |[[Pêvek:Bêçavkanî/torecivîn]] |- |[[Pêvek:Bêçavkanî/zelîn]] |- |[[Pêvek:Bêçavkanî/şeebî]] |} {{veşêre-bin}} n17gda0gxwcjtttv317nkx38y67nr9g Wîkîferheng:Xebat/arşîv 1 4 1357876 6347302 6342888 2026-08-31T00:29:09Z Wikihez 7344 [[MediaWiki:Gadget-aWa.js/belgekirin|aWa]]: Li [[Gotûbêja MediaWiki:Gadget-wikt.add-examples.js#MediaWiki:Gadget-wikt.add-examples.js]] lînka nîqaşê ji [[Wîkîferheng:Xebat]] tê zêdekirin 6347302 wikitext text/x-wiki == Tercimeyên zel == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6265301#Tercimeyên_zel}} Tercimeyên [[zel]] hatine çêkirin lê "şelmaq" wekî şablon hatiye nivîsîn. Nimûne: "{{g|bg|плесница}}"—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) :{{çêbû}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:13, 17 tîrmeh 2026 (UTC) {{arşîv-bin}} == Sererastkirina formata xwestina nimûneyan == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6276321#Sererastkirina_formata_xwestina_nimûneyan}} <syntaxhighlight lang="wikitext">#: {{mînak?|ku}}</syntaxhighlight> bike <syntaxhighlight lang="wikitext">#* {{bênimûne|ku}}</syntaxhighlight> [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 01:06, 19 tîrmeh 2026 (UTC) :[https://ku.wiktionary.org/w/index.php?search=insource%3A%2F%5C%23%3A+*%5C%7B%5C%7Bb%3F%C3%AA%3F%28nim%C3%BBne%7Cm%C3%AEnak%29%5C%3F%3F%28%5C%7C%5Ba-z%5D%2B%29%3F%5C%7D%5C%7D%2F&title=Taybet%3AL%C3%AAger%C3%AEn&profile=advanced&fulltext=1&ns0=1] Hejmara netîceyan 10.288: [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:37, 20 tîrmeh 2026 (UTC) :Boteke ji bo zêdekirina koda zimanî [https://ku.wiktionary.org/w/index.php?title=Taybet:L%C3%AAger%C3%AEn&limit=20&offset=120&profile=default&search=insource%3A%2Fb%3F%C3%AA%3Fm%C3%AEnak%5C%3F%3F%5C%7D%5C%7D%2F&ns0=1] lazim e. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 18:20, 20 tîrmeh 2026 (UTC) :{{çêbû}}--[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:31, 21 tîrmeh 2026 (UTC) {{arşîv-bin}} == MediaWiki:Gadget-aWa.js == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6276324#MediaWiki:Gadget-aWa.js}} Divê were rojanekirin ji bo ku di mobîlê de jî bixebite.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:59, 17 tîrmeh 2026 (UTC) : Ez dibêjim çêbû lê bila hinekî din test bikim dûre em bar bikin: * [[Bikarhêner:Wikihez/Gadget-aWa.css]] --> [[MediaWiki:Gadget-aWa.css]] * [[Bikarhêner:Wikihez/Gadget-aWa.js]] --> [[MediaWiki:Gadget-aWa.js]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:04, 17 tîrmeh 2026 (UTC) :Min formata [[WF:Xebat]] wisa kir ku li [[WF:Xebat/arşîv 1]] arşîv bike lê niha dibêjim bila li gotûbêja sayfeyên xwe were zêde kirin wê baştir be. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:11, 19 tîrmeh 2026 (UTC) ::Lînkek li gotûbêja sayfeya eleqedar were dayîn bes e, wekî din li arşîv 1 were qeydkirin qet nebe dîtina wan hêsantir be. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:27, 19 tîrmeh 2026 (UTC) :::Ev jî çêbû. {{r|Bikarhêner}} dikarî rûpelên jêr kopî paste bikî? * [[Bikarhêner:Wikihez/Gadget-aWa.css]] --> [[MediaWiki:Gadget-aWa.css]] * [[Bikarhêner:Wikihez/Gadget-aWa.js]] --> [[MediaWiki:Gadget-aWa.js]] --[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 17:02, 19 tîrmeh 2026 (UTC) :{{çêbû}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 14:37, 21 tîrmeh 2026 (UTC) {{arşîv-bin}} == MediaWiki:Newarticletext == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6291786#MediaWiki:Newarticletext}} * [[MediaWiki:Newarticletext]]: Divê rengên wê were rastkirin.—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:{{çêbû}} çavê min kor dikir wextê [[WF:Nû]] rast dikim {{=D}} [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 20:08, 26 tîrmeh 2026 (UTC) {{arşîv-bin}} == Modul:dara kategoriyan == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6291787#Modul:dara_kategoriyan}} * [[Modul:dara kategoriyan]] link_box —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:{{çêbû}} feqat [[Modul:dara kategoriyan/zimankatbike]] çênabe. Claude serê xwar dîsa nebû. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:24, 26 tîrmeh 2026 (UTC) *::ew jî çêbû [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:35, 26 tîrmeh 2026 (UTC) {{arşîv-bin}} == Şablon:bêçavkanî == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6325766#Şablon:bêçavkanî}} * Moda tarî de xirab e —[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:{{çêbû}} Ez dibêm îcar di moda tarî de baş bû rengên we. [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:24, 4 tebax 2026 (UTC) *::Na baş nebûye lînk zêde şîn in [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 22:32, 5 tebax 2026 (UTC) {{arşîv-bin}} == Şablon:de-tew-nerm-ern == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6327960#Şablon:de-tew-nerm-ern}} *Moda tarî de xweş nîne—[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 16:17, 16 tîrmeh 2026 (UTC) *:Min {{ş|tabloya-tewandinê-ser}} zêde kir. Înşela {{çêbû}}be [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 19:34, 4 tebax 2026 (UTC) {{arşîv-bin}} == MediaWiki:Gadget-start.js == : ''Binêre [[Gotûbêja MediaWiki:Gadget-start.js#MediaWiki:Gadget-start.js]].''[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 23:10, 18 tebax 2026 (UTC) == Mewlûd == {{arşîv-ser|xebat|archived|link=Taybet:PermanentLink/6342883#Mewlûd}} Sererastkirina jêgirtinên mewlûdê [https://ku.wiktionary.org/w/index.php?search=insource%3A%2Fw%5C%3AMela+His%C3%AAn%C3%AA+Batey%C3%AE%2F&title=Taybet%3AL%C3%AAger%C3%AEn&ns0=1&searchToken=8m0tguy3sqt7edr4sg0u8hedo] wekî [https://ku.wiktionary.org/w/index.php?title=dax%C3%AEdar&curid=284303&diff=6265851&oldid=6142285] [[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 09:43, 20 tîrmeh 2026 (UTC) {{arşîv-bin}} == MediaWiki:Gadget-wikt.add-examples.js == : ''Binêre [[Gotûbêja MediaWiki:Gadget-wikt.add-examples.js#MediaWiki:Gadget-wikt.add-examples.js]].''[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 00:29, 31 tebax 2026 (UTC) cgkkhin4ef09l30hbpbt24t8kz7pjsj ھاوەڵناو 0 1358734 6347259 6337623 2026-08-30T20:38:00Z Wikihez 7344 /* Navdêr */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347259 wikitext text/x-wiki == {{ziman|ckb}} == === Navdêr === {{navdêr|ckb}} # {{f|ckb|rêziman}} [[sifet]], [[rengdêr]] #* {{bêmînak|ckb}} ==== Etîmolojî ==== Ji {{pêk|ckb|ھاوەڵ|ناو}}. 4lxk25ulwp6whng0a53nxx86xqonddy Bikarhêner:Wikihez/Gadget-DefSideBoxes.js 2 1358875 6347249 2026-08-30T20:05:13Z Wikihez 7344 Rûpel bi "// Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and..." hat çêkirin 6347249 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane" }, { key: "dijmane", label: "Dijmane" }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Builds the small inline "word1, word2, ..." input for one sense group, saved via insertSenseWords(). function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var $input = $("<input type='text' class='dsb-input'>") .attr("placeholder", group.label + "… (kelîmeyan bi \",\" ji hev veqetîne)"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $form = $("<span class='dsb-inline-form'></span>").append($input, $save, $cancel, $status); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = $.map(($input.val() || "").split(","), function (w) { return $.trim(w); }).filter(function (w) { return !!w; }); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.css("color", "green").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.css("color", "red").text(message); } ); }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: a menu with the add-examples proxy + the 6 sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); $menu.hide(); handler(); }); $menu.append($("<li></li>").append($a)); } addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); SENSE_GROUPS.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { $li.find(".dsb-inline-form").remove(); var $form = buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group); $toolbar.after($form); $form.find(".dsb-input").trigger("focus"); }); }); $toggle.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $toolbar.append($toggle, $menu); $li.prepend($toolbar); } // One shared document-level handler closes any open menu on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } function renderField() { var s = currentSubsection(); $fieldWrap.empty(); if (s.kind === "wordlist") { $fieldWrap.append( $("<input type='text' class='dsb-input dsb-subsection-words'>") .attr("placeholder", s.header + "… (kelîmeyan bi \",\" ji hev veqetîne)") ); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = $.map(($fieldWrap.find(".dsb-subsection-words").val() || "").split(","), function (w) { return $.trim(w); }).filter(function (w) { return !!w; }); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.css("color", "green").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.css("color", "red").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $save, $status); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 3ul6klw4i7z8rw6fhehtuucy4duptrn 6347262 6347249 2026-08-30T20:47:11Z Wikihez 7344 6347262 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane" }, { key: "dijmane", label: "Dijmane" }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing pill/chip word input (start.js's own buildChipField() pattern, simplified: no suggestion panel, // just type-and-commit chips). Enter or "," commits the current text as a chip; Backspace on an empty // input removes the last chip; values() commits whatever is still typed but not yet confirmed. function buildChipInput(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-chip-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-chipfield'></span>").append($input); // Chips are direct children of $element, inserted right before $input (see addChip) -- queried the // same way, not through a separate wrapper, so this can never silently miss them. function currentValues() { var vals = []; $element.children(".dsb-chip").each(function () { vals.push($(this).data("value")); }); return vals; } function addChip(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $chip = $("<span class='dsb-chip'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-chip-remove' title='Jê bibe'>×</button>"); $remove.on("click", function () { $chip.remove(); $input.trigger("focus"); }); $chip.append($remove); $chip.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addChip($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-chip").last().remove(); } }); $input.on("blur", function () { addChip($input.val()); $input.val(""); }); return { $element: $element, values: function () { addChip($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the pill/chip word field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var chipInput = buildChipInput(group.label + "… (Enter an jî \",\" bitikîne)"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $form = $("<div class='dsb-inline-form'></div>").append(chipInput.$element, $save, $cancel, $status); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = chipInput.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); chipInput.focus(); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: a menu with the add-examples proxy + the 6 sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}" line will actually appear, instead // of squeezing the form onto the definition's own line right after the toggle. var $below = $("<div class='dsb-below'></div>"); function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); $menu.hide(); handler(); }); $menu.append($("<li></li>").append($a)); } addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); SENSE_GROUPS.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { $below.empty(); $below.append(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $toolbar.append($toggle, $menu); $li.prepend($toolbar); $li.append($below); } // One shared document-level handler closes any open menu on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordChipInput = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordChipInput = null; if (s.kind === "wordlist") { wordChipInput = buildChipInput(s.header + "… (Enter an jî \",\" bitikîne)"); $fieldWrap.append(wordChipInput.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordChipInput.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $save, $status); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 4pwd6peq9ye9slv3d3zbjojp067toff 6347264 6347262 2026-08-30T21:18:16Z Wikihez 7344 6347264 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane" }, { key: "dijmane", label: "Dijmane" }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: a menu with the add-examples proxy + the 6 sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}" line will actually appear, instead // of squeezing the form onto the definition's own line right after the toggle. var $below = $("<div class='dsb-below'></div>"); function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); $menu.hide(); handler(); }); $menu.append($("<li></li>").append($a)); } addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); SENSE_GROUPS.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { $below.empty(); $below.append(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $toolbar.append($toggle, $menu); $li.prepend($toolbar); $li.append($below); } // One shared document-level handler closes any open menu on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 47ok80pvb3fd0q3w6p37s79uhoimpkm 6347265 6347264 2026-08-30T21:21:55Z Wikihez 7344 6347265 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var ownRegex = new RegExp("^\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*"); var ownMatch = ownRegex.exec(afterMarker); if (ownMatch) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var params = ownMatch[1].split("|"); // [lang, val1, val2, ...] var existing = params.slice(1); values.forEach(function (v) { if (existing.indexOf(v) === -1) { existing.push(v); } }); lines[defLine] = marker + " {{" + tplKey + "|" + language + "|" + existing.join("|") + "}} " + afterMarker.slice(ownMatch[0].length); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Not present yet -- walk past any OTHER leading templates that outrank tplKey in // LEADING_TPL_ORDER, and insert right before the first one that doesn't (or before the gloss // text itself, if there are none). var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var rest = afterMarker; var prefix = ""; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|[^{}]*\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { var otherRank = LEADING_TPL_ORDER.indexOf(m[1]); if (otherRank === -1 || otherRank > myRank) { break; } prefix += m[0]; rest = rest.slice(m[0].length); } lines[defLine] = marker + " " + prefix + "{{" + tplKey + "|" + language + "|" + values.join("|") + "}} " + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: two always-visible quick links for Hevmane/Dijmane // (mirrors en.wiktionary's own DefSideBoxes keeping "+Add example sentence"/"+Add quotation" always // visible) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and // the remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // Always-visible quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own always-visible // "+Add example sentence"/"+Add quotation". var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickLinks.forEach(function ($a) { $toolbar.append($a); }); $toolbar.append($more, $menu); $li.prepend($toolbar); $li.append($below); } // One shared document-level handler closes any open menu on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); dxoqa9jn28myad4w5d070hzc2044jcq 6347269 6347265 2026-08-30T21:42:35Z Wikihez 7344 6347269 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Parse the whole run of leading "{{...}}" calls off the front of the line (maneid/K/e in whatever // order they're already in, plus any other template already there, e.g. a form-of call) -- stopping // at the first thing that isn't one, normally the gloss text itself. Collecting the WHOLE run (not // just tplKey's own regex against position 0) means an existing tplKey call is found and merged // wherever it already sits, not just when it happens to be first. var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: two always-visible quick links for Hevmane/Dijmane // (mirrors en.wiktionary's own DefSideBoxes keeping "+Add example sentence"/"+Add quotation" always // visible) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and // the remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // Always-visible quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own always-visible // "+Add example sentence"/"+Add quotation". var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickLinks.forEach(function ($a) { $toolbar.append($a); }); $toolbar.append($more, $menu); $li.prepend($toolbar); $li.append($below); } // One shared document-level handler closes any open menu on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 1w6h6omih4fwkazdbun5e64w3u6hwt2 6347271 6347269 2026-08-30T21:49:24Z Wikihez 7344 6347271 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Parse the whole run of leading "{{...}}" calls off the front of the line (maneid/K/e in whatever // order they're already in, plus any other template already there, e.g. a form-of call) -- stopping // at the first thing that isn't one, normally the gloss text itself. Collecting the WHOLE run (not // just tplKey's own regex against position 0) means an existing tplKey call is found and merged // wherever it already sits, not just when it happens to be first. var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: two always-visible quick links for Hevmane/Dijmane // (mirrors en.wiktionary's own DefSideBoxes keeping "+Add example sentence"/"+Add quotation" always // visible) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and // the remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); $li.append($quickRow, $below); } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); oozv9pxra90i4fk6m3s2vhess4opxh0 6347274 6347271 2026-08-30T22:00:29Z Wikihez 7344 6347274 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê wateyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Parse the whole run of leading "{{...}}" calls off the front of the line (maneid/K/e in whatever // order they're already in, plus any other template already there, e.g. a form-of call) -- stopping // at the first thing that isn't one, normally the gloss text itself. Collecting the WHOLE run (not // just tplKey's own regex against position 0) means an existing tplKey call is found and merged // wherever it already sits, not just when it happens to be first. var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: two always-visible quick links for Hevmane/Dijmane // (mirrors en.wiktionary's own DefSideBoxes keeping "+Add example sentence"/"+Add quotation" always // visible) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and // the remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê wateyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Tomar bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate tomarkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); p27bv37q1i6inxphh8nq9yrmagh9nis 6347279 6347274 2026-08-30T22:42:53Z Wikihez 7344 6347279 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgNamespaceNumber") !== 0 || mw.config.get("wgAction") !== "view") { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Builds the "Maneyê biguhêre" form -- the one primary action that changes the sense's own wording rather // than adding to it. Prefills from fetchCurrentGloss() (disabled/greyed out until that read resolves, so // there's nothing to accidentally save over before the real text has loaded), saves via updateSenseGloss(). function buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel) { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>").prop("disabled", true); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($textarea, $actions); $cancel.on("click", function () { $form.remove(); }); fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { $textarea.val(gloss).prop("disabled", false); $save.prop("disabled", false); $textarea.trigger("focus"); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $save.on("click", function () { var newGloss = $.trim($textarea.val()); if (!newGloss) { return; } $save.prop("disabled", true); editPage( "guhertina maneyê (DefSideBoxes)", function (pageContent) { return updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: "Maneyê biguhêre" plus two quick links for // Hevmane/Dijmane, all revealed by the "+" toggle (mirrors en.wiktionary's own DefSideBoxes "[synonym ▲]" // row) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and the // remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // "Maneyê biguhêre" -- edits the sense's own gloss text, so it's built and wired separately from the // SENSE_GROUPS quick links below (those only ever ADD to the line, never change existing wording). // The most primary action on a sense, so it comes first in $quickRow, ahead of Hevmane/Dijmane. var $editGlossLink = $("<a href='#' class='dsb-quick-link dsb-quick-link-edit'></a>").text("Maneyê biguhêre"); $editGlossLink.on("click", function (e) { e.preventDefault(); openForm(buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel)); }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickRow.append($editGlossLink); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 8kk40uiqmmsev9b9lp4n0pzh0y29fz3 6347281 6347279 2026-08-30T22:44:56Z Wikihez 7344 6347281 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. var PAGE_SUBSECTIONS = [ { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text of any "====" subsections it already contains. function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push(h4[1].trim()); } } return { end: end, existingHeaders: existingHeaders }; } // Inserts a new "==== Header ====" subsection at the end of a POS block, either as a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); if (bounds.existingHeaders.indexOf(subsection.header) !== -1) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } lines.splice(bounds.end, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Builds the "Maneyê biguhêre" form -- the one primary action that changes the sense's own wording rather // than adding to it. Prefills from fetchCurrentGloss() (disabled/greyed out until that read resolves, so // there's nothing to accidentally save over before the real text has loaded), saves via updateSenseGloss(). function buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel) { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>").prop("disabled", true); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($textarea, $actions); $cancel.on("click", function () { $form.remove(); }); fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { $textarea.val(gloss).prop("disabled", false); $save.prop("disabled", false); $textarea.trigger("focus"); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $save.on("click", function () { var newGloss = $.trim($textarea.val()); if (!newGloss) { return; } $save.prop("disabled", true); editPage( "guhertina maneyê (DefSideBoxes)", function (pageContent) { return updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: "Maneyê biguhêre" plus two quick links for // Hevmane/Dijmane, all revealed by the "+" toggle (mirrors en.wiktionary's own DefSideBoxes "[synonym ▲]" // row) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and the // remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // "Maneyê biguhêre" -- edits the sense's own gloss text, so it's built and wired separately from the // SENSE_GROUPS quick links below (those only ever ADD to the line, never change existing wording). // The most primary action on a sense, so it comes first in $quickRow, ahead of Hevmane/Dijmane. var $editGlossLink = $("<a href='#' class='dsb-quick-link dsb-quick-link-edit'></a>").text("Maneyê biguhêre"); $editGlossLink.on("click", function (e) { e.preventDefault(); openForm(buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel)); }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickRow.append($editGlossLink); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); lundcxn917girelplpj4p4b9y1evfc4 6347298 6347281 2026-08-31T00:20:50Z Wikihez 7344 6347298 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Builds the "Maneyê biguhêre" form -- the one primary action that changes the sense's own wording rather // than adding to it. Prefills from fetchCurrentGloss() (disabled/greyed out until that read resolves, so // there's nothing to accidentally save over before the real text has loaded), saves via updateSenseGloss(). function buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel) { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>").prop("disabled", true); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($textarea, $actions); $cancel.on("click", function () { $form.remove(); }); fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { $textarea.val(gloss).prop("disabled", false); $save.prop("disabled", false); $textarea.trigger("focus"); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $save.on("click", function () { var newGloss = $.trim($textarea.val()); if (!newGloss) { return; } $save.prop("disabled", true); editPage( "guhertina maneyê (DefSideBoxes)", function (pageContent) { return updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: "Maneyê biguhêre" plus two quick links for // Hevmane/Dijmane, all revealed by the "+" toggle (mirrors en.wiktionary's own DefSideBoxes "[synonym ▲]" // row) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and the // remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>+</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // "Maneyê biguhêre" -- edits the sense's own gloss text, so it's built and wired separately from the // SENSE_GROUPS quick links below (those only ever ADD to the line, never change existing wording). // The most primary action on a sense, so it comes first in $quickRow, ahead of Hevmane/Dijmane. var $editGlossLink = $("<a href='#' class='dsb-quick-link dsb-quick-link-edit'></a>").text("Maneyê biguhêre"); $editGlossLink.on("click", function (e) { e.preventDefault(); openForm(buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel)); }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickRow.append($editGlossLink); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); bomislmyrae2iprvjfsh8svxx0c1313 6347307 6347298 2026-08-31T00:38:17Z Wikihez 7344 6347307 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Builds the "Maneyê biguhêre" form -- the one primary action that changes the sense's own wording rather // than adding to it. Prefills from fetchCurrentGloss() (disabled/greyed out until that read resolves, so // there's nothing to accidentally save over before the real text has loaded), saves via updateSenseGloss(). function buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel) { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>").prop("disabled", true); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($textarea, $actions); $cancel.on("click", function () { $form.remove(); }); fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { $textarea.val(gloss).prop("disabled", false); $save.prop("disabled", false); $textarea.trigger("focus"); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $save.on("click", function () { var newGloss = $.trim($textarea.val()); if (!newGloss) { return; } $save.prop("disabled", true); editPage( "guhertina maneyê (DefSideBoxes)", function (pageContent) { return updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: "Maneyê biguhêre" plus two quick links for // Hevmane/Dijmane, all revealed by the "+" toggle (mirrors en.wiktionary's own DefSideBoxes "[synonym ▲]" // row) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and the // remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>✎</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // "Maneyê biguhêre" -- edits the sense's own gloss text, so it's built and wired separately from the // SENSE_GROUPS quick links below (those only ever ADD to the line, never change existing wording). // The most primary action on a sense, so it comes first in $quickRow, ahead of Hevmane/Dijmane. var $editGlossLink = $("<a href='#' class='dsb-quick-link dsb-quick-link-edit'></a>").text("Maneyê biguhêre"); $editGlossLink.on("click", function (e) { e.preventDefault(); openForm(buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel)); }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickRow.append($editGlossLink); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); editPage( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return convertManeToPos(pageContent, language, maneOrdinal, chosen); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 0ybrbejq8s1zwqh7szmn1ndkm1jc0th 6347312 6347307 2026-08-31T00:53:33Z Wikihez 7344 6347312 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the word-list field for one sense group, saved via insertSenseWords(). Appended below the // definition's own content (see attachToolbar's $below), not squeezed inline next to the "+" toggle. function buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group) { var wordField = buildWordListField(group.label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(wordField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var words = wordField.values(); if (!words.length) { return; } $save.prop("disabled", true); editPage( "+" + group.label + " (DefSideBoxes)", function (pageContent) { return insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); wordField.focus(); return $form; } // Builds the tag field for Etîket or Kategorî ({{e|lang|...}} / {{K|lang|...}}), saved via // insertLeadingSenseTpl(). Same $below placement as buildSenseGroupForm(). function buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, tplKey, label) { var tagField = buildTagField(label + "…"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append(tagField.$element, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var values = tagField.values(); if (!values.length) { return; } $save.prop("disabled", true); editPage( "+" + label + " (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); tagField.focus(); return $form; } // Builds the single-id form for {{maneid|lang|id}}, saved via insertLeadingSenseTpl() with noExtend // (a sense's id must never be silently overwritten by a second, different one). Same $below placement. function buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel) { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($input, $actions); $cancel.on("click", function () { $form.remove(); }); $save.on("click", function () { var id = $.trim($input.val()); if (!id) { return; } $save.prop("disabled", true); editPage( "+nasnav (DefSideBoxes)", function (pageContent) { return insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [id], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $input.trigger("focus"); return $form; } // Builds the "Maneyê biguhêre" form -- the one primary action that changes the sense's own wording rather // than adding to it. Prefills from fetchCurrentGloss() (disabled/greyed out until that read resolves, so // there's nothing to accidentally save over before the real text has loaded), saves via updateSenseGloss(). function buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel) { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>").prop("disabled", true); // Runs the gloss text through linkifyText() on demand -- same gadget the automatic zero-links fallback // in $save's own handler below uses, just triggered manually so the user can see/tweak the result // before saving. var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $autoLink, $cancel, $status); var $form = $("<div class='dsb-inline-form'></div>").append($textarea, $actions); $cancel.on("click", function () { $form.remove(); }); fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { $textarea.val(gloss).prop("disabled", false); $save.prop("disabled", false); $autoLink.prop("disabled", false); $textarea.trigger("focus"); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $status.text(""); }); }); $save.on("click", function () { var newGloss = $.trim($textarea.val()); if (!newGloss) { return; } $save.prop("disabled", true); $autoLink.prop("disabled", true); function doSave(finalGloss) { editPage( "guhertina maneyê (DefSideBoxes)", function (pageContent) { return updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, finalGloss); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $autoLink.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } // A gloss with at least one manual [[...]] link is saved exactly as written -- the user has // already curated its links deliberately. One with zero links gets auto-linkified first, same // rule (and same underlying gadget) as the standalone "Oto-lînk bike" button, just applied // automatically so it's never simply forgotten. if (/\[\[.+?\]\]/.test(newGloss)) { doSave(newGloss); } else { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(newGloss, function (linked) { var linkedTrimmed = $.trim(linked); $textarea.val(linkedTrimmed); doSave(linkedTrimmed); }); } }); return $form; } // Attaches the "+" toolbar to one leaf definition <li>: "Maneyê biguhêre" plus two quick links for // Hevmane/Dijmane, all revealed by the "+" toggle (mirrors en.wiktionary's own DefSideBoxes "[synonym ▲]" // row) plus a "More" menu for everything else -- the add-examples proxy, maneid, etîket, kategorî and the // remaining sense groups. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Beşên zêde'>✎</a>"); // Revealed by $toggle -- an indented row under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); var $more = $("<a href='#' class='dsb-more-toggle'>Zêdetir &#9662;</a>"); var $menu = $("<ul class='dsb-menu'></ul>").hide(); // Opened forms always land here -- the last child of the <li>, below any existing citation/example // content -- matching where the eventual rendered "#: {{tpl|...}}"/inline-template output will // actually appear, instead of squeezing the form onto the definition's own line. var $below = $("<div class='dsb-below'></div>"); function openForm($form) { $menu.hide(); $below.empty(); $below.append($form); } function addItem(label, handler) { var $a = $("<a href='#'></a>").text(label); $a.on("click", function (e) { e.preventDefault(); handler(); }); $menu.append($("<li></li>").append($a)); } var primaryGroups = SENSE_GROUPS.filter(function (g) { return g.primary; }); var secondaryGroups = SENSE_GROUPS.filter(function (g) { return !g.primary; }); // "Maneyê biguhêre" -- edits the sense's own gloss text, so it's built and wired separately from the // SENSE_GROUPS quick links below (those only ever ADD to the line, never change existing wording). // The most primary action on a sense, so it comes first in $quickRow, ahead of Hevmane/Dijmane. var $editGlossLink = $("<a href='#' class='dsb-quick-link dsb-quick-link-edit'></a>").text("Maneyê biguhêre"); $editGlossLink.on("click", function (e) { e.preventDefault(); openForm(buildEditGlossForm(language, sectionType, sectionOrdinal, definitionLevel)); }); // Quick links -- Hevmane/Dijmane -- same idea as en.wiktionary's own "+Add example sentence"/ // "+Add quotation", but (like that row) only shown once $toggle is clicked, not always visible. var $quickLinks = primaryGroups.map(function (group) { var $a = $("<a href='#' class='dsb-quick-link'></a>").text("+ " + group.label); $a.on("click", function (e) { e.preventDefault(); openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); return $a; }); // Everything else lives inside "More": the add-examples proxy, maneid, etîket, kategorî, then the // remaining sense groups (Formek alternatîv, Termek koordîne, Jornav, Jêrnav). addItem("Nimûne/jêgirtin lê zêde bike", function () { var $btn = findExampleButton($li); if ($btn) { $menu.hide(); $btn.trigger("click"); } else { $menu.hide(); mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); addItem("Nasnavek lê zêde bike (maneid)", function () { openForm(buildManeIdForm(language, sectionType, sectionOrdinal, definitionLevel)); }); addItem("Etîket lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "e", "Etîket")); }); addItem("Kategorî lê zêde bike", function () { openForm(buildInlineTplForm(language, sectionType, sectionOrdinal, definitionLevel, "K", "Kategorî")); }); secondaryGroups.forEach(function (group) { addItem(group.label + " lê zêde bike", function () { openForm(buildSenseGroupForm(language, sectionType, sectionOrdinal, definitionLevel, group)); }); }); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); }); $more.on("click", function (e) { e.preventDefault(); e.stopPropagation(); $(".dsb-menu").not($menu).hide(); $menu.toggle(); }); $menu.on("click", function (e) { e.stopPropagation(); }); $quickRow.append($editGlossLink); $quickLinks.forEach(function ($a) { $quickRow.append($a); }); $quickRow.append($more, $menu); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow (and $below, so an opened form appears right where its trigger was rather than // far below) right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow, $below); } else { $li.append($quickRow, $below); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); editPage( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return convertManeToPos(pageContent, language, maneOrdinal, chosen); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 821f8sgkdgxsv3rwz10707bwniwmjui 6347317 6347312 2026-08-31T01:20:21Z Wikihez 7344 6347317 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- "guhartina pêşketî" (advanced editing): combine several independent per-sense edits into ONE save ---- // Threads pageContent through the same pure functions every single-field form already used // (updateSenseGloss/insertLeadingSenseTpl/insertSenseWords/insertPageSubsection), applying only the // pieces the caller actually filled in (see buildAdvancedPanel()'s own collectChanges()). A piece that // conflicts with something already on the page (maneid already set, a subsection that's already there) // is skipped with a warning rather than failing the whole save -- everything else the user changed still // goes through in the same edit. Throws SubmitAbort if literally nothing was filled in, so this can never // turn into a no-op save. function applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes) { var content = pageContent; var warnings = []; var appliedAnything = false; function tryApply(fn) { try { content = fn(); appliedAnything = true; } catch (e) { if (e instanceof SubmitAbort) { warnings.push(e.message); } else { throw e; } } } if (changes.gloss) { content = updateSenseGloss(content, language, sectionType, sectionOrdinal, definitionLevel, changes.gloss); appliedAnything = true; } if (changes.maneid) { tryApply(function () { return insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [changes.maneid], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }); } if (changes.etiket && changes.etiket.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "e", changes.etiket); appliedAnything = true; } if (changes.kategori && changes.kategori.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "K", changes.kategori); appliedAnything = true; } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { content = insertSenseWords(content, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); appliedAnything = true; } }); if (changes.subsection) { tryApply(function () { return insertPageSubsection(content, language, sectionType, sectionOrdinal, changes.subsection.def, changes.subsection.content); }); } if (!appliedAnything) { throw new SubmitAbort("Tiştek nehat guhertin."); } return { content: content, warnings: warnings }; } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the whole "guhartina pêşketî" panel into $quickRow: gloss (+ Oto-lînk bike), every SENSE_GROUPS // word list, maneid, etîket, kategorî, and this POS block's own "+ beşek" subsection picker, plus one // shared Qeyd bike that saves everything the user actually filled in as a single edit, via // applyAdvancedChanges(). Nimûne/jêgirtin stays a separate, immediate proxy-click (see findExampleButton()) // -- it opens a DIFFERENT gadget's own form with its own independent save, so it can't be folded into // this combined transform the way every wikitext-writing field here can. function buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel) { var $nimune = $("<a href='#' class='dsb-quick-link'></a>").text("Nimûne/jêgirtin lê zêde bike"); $nimune.on("click", function (e) { e.preventDefault(); var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); // -- gloss (edits the sense's own wording -- everything else here only ever ADDS to the line) -- var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $glossStatus = $("<span class='dsb-status'></span>"); var $glossGroup = $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Mane"), $textarea, $("<div class='dsb-form-actions'></div>").append($autoLink, $glossStatus) ); var originalGloss = null; fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { originalGloss = gloss; $textarea.val(gloss).prop("disabled", false); $autoLink.prop("disabled", false); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $glossStatus.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $glossStatus.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $glossStatus.text(""); }); }); // -- every SENSE_GROUPS word list (Hevmane/Dijmane and the rest -- not just the two most common) -- var wordFields = {}; var $wordGroups = SENSE_GROUPS.map(function (group) { var field = buildWordListField(group.label + "…"); wordFields[group.key] = field; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text(group.label), field.$element); }); // -- maneid (single value; re-adding one that already exists is rejected -- see applyAdvancedChanges) -- var $maneidInput = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); var $maneidGroup = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Nasnav (maneid)"), $maneidInput); // -- etîket / kategorî -- var etiketField = buildTagField("Etîket…"); var $etiketGroup = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Etîket"), etiketField.$element); var kategoriField = buildTagField("Kategorî…"); var $kategoriGroup = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Kategorî"), kategoriField.$element); // -- this POS block's own "====" subsections (same picker buildSubsectionPanel() uses, folded in here) -- var existingHeaders = existingSubsectionHeadersInDom($h3); var availableSubsections = PAGE_SUBSECTIONS.filter(function (s) { return existingHeaders.indexOf(s.header) === -1; }); var $subGroup; var $subSelect = null; var $subFieldWrap = $("<div class='dsb-subsection-field'></div>"); var subWordField = null; function currentSubsection() { var id = $subSelect.val(); return availableSubsections.filter(function (s) { return s.id === id; })[0]; } if (availableSubsections.length) { $subSelect = $("<select class='dsb-subsection-select'></select>"); availableSubsections.forEach(function (s) { $subSelect.append($("<option></option>").val(s.id).text(s.header)); }); function renderSubField() { var s = currentSubsection(); $subFieldWrap.empty(); subWordField = null; if (s.kind === "wordlist") { subWordField = buildWordListField(s.header + "…"); $subFieldWrap.append(subWordField.$element); } else { $subFieldWrap.append($("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>").attr("placeholder", s.header + "…")); } } $subSelect.on("change", renderSubField); renderSubField(); $subGroup = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Beşek (====)"), $subSelect, $subFieldWrap); } else { $subGroup = $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Beşek (====)"), $("<div class='dsb-status'></div>").text("Hemû beş jixwe li vê hene.") ); } // -- combined save -- var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); $cancel.on("click", function () { $quickRow.hide(); }); function collectChanges() { var glossVal = $.trim($textarea.val()); var words = {}; SENSE_GROUPS.forEach(function (group) { words[group.key] = wordFields[group.key].values(); }); var subsection = null; if (availableSubsections.length) { var s = currentSubsection(); var subContent = s.kind === "wordlist" ? subWordField.values() : $.trim($subFieldWrap.find(".dsb-subsection-text").val() || ""); var hasSubContent = s.kind === "wordlist" ? subContent.length > 0 : subContent !== ""; if (hasSubContent) { subsection = { def: s, content: subContent }; } } return { // Only re-save the gloss if it's non-empty AND actually different from what was loaded -- // an untouched textarea (or one still showing the same text) should never trigger a rewrite. gloss: (glossVal && glossVal !== originalGloss) ? glossVal : null, maneid: $.trim($maneidInput.val()), etiket: etiketField.values(), kategori: kategoriField.values(), words: words, subsection: subsection }; } $save.on("click", function () { var changes = collectChanges(); var warnings = []; $save.prop("disabled", true); function doSave() { editPage( "guhartina pêşketî (DefSideBoxes)", function (pageContent) { var result = applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes); warnings = result.warnings; return result.content; }, function () { var okText = "✓ hate qeydkirin — rûpel nûve bike da ku bibînî."; if (warnings.length) { okText += " (" + warnings.join(" ") + ")"; } $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text(okText); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } // Same zero-links-gets-auto-linkified rule as the standalone gloss-edit form (round 10) -- // only when the gloss is actually part of this save, and only ever applied automatically when // the user hasn't already added a manual link themselves. if (changes.gloss && !/\[\[.+?\]\]/.test(changes.gloss)) { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(changes.gloss, function (linked) { var linkedTrimmed = $.trim(linked); $textarea.val(linkedTrimmed); changes.gloss = linkedTrimmed; doSave(); }); } else { doSave(); } }); $quickRow.empty().append($nimune, $glossGroup); $wordGroups.forEach(function ($g) { $quickRow.append($g); }); $quickRow.append($maneidGroup, $etiketGroup, $kategoriGroup, $subGroup, $actions); } // Attaches the pencil toggle to one leaf definition <li> -- clicking it reveals the "guhartina pêşketî" // (advanced editing) panel built by buildAdvancedPanel() above: every action this gadget offers for this // sense, plus this POS block's own subsections, saved together with one Qeyd bike. Replaces the old // separate quick-links row + "More" menu (round 10) so multiple changes never need multiple separate edits. function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Guhartina pêşketî'>✎</a>"); // Revealed by $toggle -- an indented panel under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. Built // lazily on first open (see buildAdvancedPanel()'s own fetchCurrentGloss() call) rather than eagerly // for every sense on the page. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); if ($quickRow.is(":visible") && !$quickRow.data("built")) { buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel); $quickRow.data("built", true); } }); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow); } else { $li.append($quickRow); } } // One shared document-level handler closes any open menu (but not the quick-row itself -- that stays // open until $toggle is clicked again) on an outside click. $(document).on("click", function () { $(".dsb-menu").hide(); }); // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); editPage( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return convertManeToPos(pageContent, language, maneOrdinal, chosen); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); bq91723dhjcm5t3lz7q52k3o0rvzygk 6347319 6347317 2026-08-31T06:37:49Z Wikihez 7344 6347319 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- "guhartina pêşketî" (advanced editing): combine several independent per-sense edits into ONE save ---- // Threads pageContent through the same pure functions every single-field form already used // (updateSenseGloss/insertLeadingSenseTpl/insertSenseWords/insertPageSubsection), applying only the // pieces the caller actually filled in (see buildAdvancedPanel()'s own collectChanges()). A piece that // conflicts with something already on the page (maneid already set, a subsection that's already there) // is skipped with a warning rather than failing the whole save -- everything else the user changed still // goes through in the same edit. Throws SubmitAbort if literally nothing was filled in, so this can never // turn into a no-op save. function applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes) { var content = pageContent; var warnings = []; var appliedAnything = false; function tryApply(fn) { try { content = fn(); appliedAnything = true; } catch (e) { if (e instanceof SubmitAbort) { warnings.push(e.message); } else { throw e; } } } if (changes.gloss) { content = updateSenseGloss(content, language, sectionType, sectionOrdinal, definitionLevel, changes.gloss); appliedAnything = true; } if (changes.maneid) { tryApply(function () { return insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [changes.maneid], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }); } if (changes.etiket && changes.etiket.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "e", changes.etiket); appliedAnything = true; } if (changes.kategori && changes.kategori.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "K", changes.kategori); appliedAnything = true; } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { content = insertSenseWords(content, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); appliedAnything = true; } }); if (changes.subsection) { tryApply(function () { return insertPageSubsection(content, language, sectionType, sectionOrdinal, changes.subsection.def, changes.subsection.content); }); } if (!appliedAnything) { throw new SubmitAbort("Tiştek nehat guhertin."); } return { content: content, warnings: warnings }; } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the whole "guhartina pêşketî" panel into $quickRow: gloss (+ Oto-lînk bike), every SENSE_GROUPS // word list, maneid, etîket, kategorî, and this POS block's own "+ beşek" subsection picker, plus one // shared Qeyd bike that saves everything the user actually filled in as a single edit, via // applyAdvancedChanges(). Nimûne/jêgirtin stays a separate, immediate proxy-click (see findExampleButton()) // -- it opens a DIFFERENT gadget's own form with its own independent save, so it can't be folded into // this combined transform the way every wikitext-writing field here can. function buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel) { var $nimune = $("<a href='#' class='dsb-quick-link'></a>").text("Nimûne/jêgirtin lê zêde bike"); $nimune.on("click", function (e) { e.preventDefault(); var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); // getters holds one function per currently-OPEN box (key -> () => value); collectChanges() below only // ever reads from a box the user actually clicked to add -- there is no "always all 11 fields present" // state any more (that was tried and reverted -- see this file's own history notes). var getters = {}; // -- gloss ("Maneyê biguhêre" -- the one box that EDITS the sense's own wording; everything else here // only ever ADDS to the definition line) -- function addGlossField() { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $status = $("<span class='dsb-status'></span>"); var originalGloss = null; fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { originalGloss = gloss; $textarea.val(gloss).prop("disabled", false); $autoLink.prop("disabled", false); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $status.text(""); }); }); getters.gloss = function () { var v = $.trim($textarea.val()); return (v && v !== originalGloss) ? v : null; }; return $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Mane"), $textarea, $("<div class='dsb-form-actions'></div>").append($autoLink, $status) ); } // -- one SENSE_GROUPS word-list box (Hevmane/Dijmane/etc.) -- function addWordField(group) { var field = buildWordListField(group.label + "…"); getters["word:" + group.key] = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text(group.label), field.$element); } // -- maneid (single value; re-adding one that already exists is rejected -- see applyAdvancedChanges) -- function addManeidField() { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); getters.maneid = function () { return $.trim($input.val()); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Nasnav (maneid)"), $input); } // -- etîket / kategorî -- function addEtiketField() { var field = buildTagField("Etîket…"); getters.etiket = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Etîket"), field.$element); } function addKategoriField() { var field = buildTagField("Kategorî…"); getters.kategori = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Kategorî"), field.$element); } // -- this POS block's own "====" subsections (same picker buildSubsectionPanel() uses, folded in here) -- function addSubsectionField() { var existingHeaders = existingSubsectionHeadersInDom($h3); var availableSubsections = PAGE_SUBSECTIONS.filter(function (s) { return existingHeaders.indexOf(s.header) === -1; }); var $wrap = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Beşek (====)")); if (!availableSubsections.length) { $wrap.append($("<div class='dsb-status'></div>").text("Hemû beş jixwe li vê hene.")); return $wrap; } var $select = $("<select class='dsb-subsection-select'></select>"); availableSubsections.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var subWordField = null; function currentSubsection() { var id = $select.val(); return availableSubsections.filter(function (s) { return s.id === id; })[0]; } function renderSubField() { var s = currentSubsection(); $fieldWrap.empty(); subWordField = null; if (s.kind === "wordlist") { subWordField = buildWordListField(s.header + "…"); $fieldWrap.append(subWordField.$element); } else { $fieldWrap.append($("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>").attr("placeholder", s.header + "…")); } } $select.on("change", renderSubField); renderSubField(); getters.subsection = function () { var s = currentSubsection(); var content = s.kind === "wordlist" ? subWordField.values() : $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); var hasContent = s.kind === "wordlist" ? content.length > 0 : content !== ""; return hasContent ? { def: s, content: content } : null; }; $wrap.append($select, $fieldWrap); return $wrap; } // -- the picker row: one "+ <label>" link per addable box (gloss's own link has no "+", it EDITS rather // than adds). Clicking one builds and appends its box to $openBoxes and hides that link; the box's own // "×" removes it, clears its getter, and un-hides the link -- several boxes can be open at once, unlike // the old "only one form open at a time" behavior (round 3-10's $below). ---- var FIELD_DEFS = [{ key: "gloss", label: "Maneyê biguhêre", build: addGlossField }] .concat(SENSE_GROUPS.map(function (group) { return { key: "word:" + group.key, label: group.label, build: function () { return addWordField(group); } }; })) .concat([ { key: "maneid", label: "Nasnav (maneid)", build: addManeidField }, { key: "etiket", label: "Etîket", build: addEtiketField }, { key: "kategori", label: "Kategorî", build: addKategoriField }, { key: "subsection", label: "Beşek (====)", build: addSubsectionField } ]); var $picker = $("<div class='dsb-field-picker'></div>"); var $openBoxes = $("<div class='dsb-open-boxes'></div>"); FIELD_DEFS.forEach(function (def) { var $link = $("<a href='#' class='dsb-quick-link dsb-field-pick'></a>").text(def.key === "gloss" ? def.label : "+ " + def.label); $link.on("click", function (e) { e.preventDefault(); var $box = def.build(); var $remove = $("<a href='#' class='dsb-box-remove' title='Rake'>×</a>"); $remove.on("click", function (e2) { e2.preventDefault(); delete getters[def.key]; $box.remove(); $link.show(); }); $box.prepend($remove); $openBoxes.append($box); $link.hide(); }); $picker.append($link); }); // -- combined save: whatever boxes are open right now, saved together. Prefers queuing into the real // window.editor singleton (Gadget-Editor.js / "Gadget-Editor - kuwikt.js", already on this wiki) via its // own edit()/wikitext() API -- its own floating widget then does the actual single mw.Api().edit() POST, // possibly batched together with other gadgets' own queued changes too. Falls back to this file's own // direct editPage() (unchanged from every earlier round) when window.editor isn't loaded/available, e.g. // when viewing an old revision (editor.js's own guard then makes window.editor === {}) -- same // never-block-on-a-missing-gadget philosophy as linkifyText()'s own fallback. ---- function hasEditor() { return typeof window.editor === "object" && window.editor !== null && typeof window.editor.edit === "function" && typeof window.editor.wikitext === "function"; } function collectChanges() { var words = {}; SENSE_GROUPS.forEach(function (group) { var getter = getters["word:" + group.key]; words[group.key] = getter ? getter() : []; }); return { gloss: getters.gloss ? getters.gloss() : null, maneid: getters.maneid ? getters.maneid() : "", etiket: getters.etiket ? getters.etiket() : [], kategori: getters.kategori ? getters.kategori() : [], words: words, subsection: getters.subsection ? getters.subsection() : null }; } var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); $cancel.on("click", function () { $quickRow.hide(); }); $save.on("click", function () { var changes = collectChanges(); function afterLinkify() { if (hasEditor()) { window.editor.wikitext().then(function (baseContent) { var result; try { result = applyAdvancedChanges(baseContent, language, sectionType, sectionOrdinal, definitionLevel, changes); } catch (e) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(e instanceof SubmitAbort ? e.message : "Xeletiyeke nenas."); return; } window.editor.edit({ wikitext: result.content, redo: function () {}, undo: function () {}, summary: "guhartina pêşketî (DefSideBoxes)", summary_type: "dsb" }); var queuedText = "✓ li rêza guhertinan hate zêdekirin — pêl bişkoja qeydkirinê ya li serê rûpelê bike da ku bicîh bibe."; if (result.warnings.length) { queuedText += " (" + result.warnings.join(" ") + ")"; } $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text(queuedText); $save.prop("disabled", false); }, function () { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Nekarî muhtewaya rûpelê ya heyî bar bike."); }); } else { var warnings = []; editPage( "guhartina pêşketî (DefSideBoxes)", function (pageContent) { var result = applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes); warnings = result.warnings; return result.content; }, function () { var okText = "✓ hate qeydkirin — rûpel nûve bike da ku bibînî."; if (warnings.length) { okText += " (" + warnings.join(" ") + ")"; } $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text(okText); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } } $save.prop("disabled", true); // Same zero-links-gets-auto-linkified rule as every earlier round's gloss save -- only when the // gloss is actually part of this save, and only ever applied automatically when the user hasn't // already added a manual link themselves. if (changes.gloss && !/\[\[.+?\]\]/.test(changes.gloss)) { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(changes.gloss, function (linked) { changes.gloss = $.trim(linked); afterLinkify(); }); } else { afterLinkify(); } }); $quickRow.empty().append($nimune, $picker, $openBoxes, $actions); } // Attaches the pencil toggle to one leaf definition <li> -- clicking it reveals the "guhartina pêşketî" // (advanced editing) panel built by buildAdvancedPanel() above: a picker of "+ <field>" links (gloss, // each SENSE_GROUPS word list, maneid, etîket, kategorî, this POS block's own subsections) lets the user // open several boxes at once, then one shared Qeyd bike saves everything currently open together -- // queued into the real window.editor singleton when it's available, falling back to this file's own // direct editPage() otherwise. Replaces the old separate quick-links row + "More" menu (round 10). function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Guhartina pêşketî'>✎</a>"); // Revealed by $toggle -- an indented panel under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. Built // lazily on first open (see buildAdvancedPanel()'s own fetchCurrentGloss() call) rather than eagerly // for every sense on the page. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); if ($quickRow.is(":visible") && !$quickRow.data("built")) { buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel); $quickRow.data("built", true); } }); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow); } else { $li.append($quickRow); } } // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); editPage( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); editPage( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return convertManeToPos(pageContent, language, maneOrdinal, chosen); }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hate qeydkirin — rûpel nûve bike da ku bibînî."); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); 92v25924iryr5viuwu7ob263oa7468f 6347324 6347319 2026-08-31T09:40:49Z Wikihez 7344 6347324 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // True only when the real Gadget-Editor.js singleton ("Gadget-Editor - kuwikt.js", already on this wiki) is // loaded and actually usable. It becomes {} (no methods) when viewing an old revision -- see its own guard -- // so a plain typeof/property check is not enough; every method this file calls must be confirmed present. function hasEditor() { return typeof window.editor === "object" && window.editor !== null && typeof window.editor.edit === "function" && typeof window.editor.wikitext === "function"; } // Runs transformFn(baseWikitext) -> {content, warnings}, then either queues the result into the real // window.editor singleton (its own floating widget does the actual single mw.Api().edit() POST, possibly // batched with other gadgets' own queued changes too) or falls back to this file's own direct editPage() // when window.editor isn't available/functional -- same never-block-on-a-missing-gadget philosophy as // linkifyText()'s own fallback below. Shared by every panel that saves a single wikitext change: // buildAdvancedPanel, buildSubsectionPanel, buildConvertPosPanel. function saveChange(summary, transformFn, $save, $status) { function withWarnings(base, warnings) { return (warnings && warnings.length) ? base + " (" + warnings.join(" ") + ")" : base; } if (hasEditor()) { window.editor.wikitext().then(function (baseContent) { var result; try { result = transformFn(baseContent); } catch (e) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(e instanceof SubmitAbort ? e.message : "Xeletiyeke nenas."); return; } window.editor.edit({ wikitext: result.content, redo: function () {}, undo: function () {}, summary: summary, summary_type: "dsb" }); $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text(withWarnings( "✓ li rêza guhertinan hate zêdekirin — pêl bişkoja qeydkirinê ya li serê rûpelê bike da ku bicîh bibe.", result.warnings )); $save.prop("disabled", false); }, function () { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Nekarî muhtewaya rûpelê ya heyî bar bike."); }); } else { var warnings = []; editPage( summary, function (pageContent) { var result = transformFn(pageContent); warnings = result.warnings; return result.content; }, function () { $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text(withWarnings("✓ hate qeydkirin — rûpel nûve bike da ku bibînî.", warnings)); }, function (message) { $save.prop("disabled", false); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- "guhartina pêşketî" (advanced editing): combine several independent per-sense edits into ONE save ---- // Threads pageContent through the same pure functions every single-field form already used // (updateSenseGloss/insertLeadingSenseTpl/insertSenseWords/insertPageSubsection), applying only the // pieces the caller actually filled in (see buildAdvancedPanel()'s own collectChanges()). A piece that // conflicts with something already on the page (maneid already set, a subsection that's already there) // is skipped with a warning rather than failing the whole save -- everything else the user changed still // goes through in the same edit. Throws SubmitAbort if literally nothing was filled in, so this can never // turn into a no-op save. function applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes) { var content = pageContent; var warnings = []; var appliedAnything = false; function tryApply(fn) { try { content = fn(); appliedAnything = true; } catch (e) { if (e instanceof SubmitAbort) { warnings.push(e.message); } else { throw e; } } } if (changes.gloss) { content = updateSenseGloss(content, language, sectionType, sectionOrdinal, definitionLevel, changes.gloss); appliedAnything = true; } if (changes.maneid) { tryApply(function () { return insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [changes.maneid], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }); } if (changes.etiket && changes.etiket.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "e", changes.etiket); appliedAnything = true; } if (changes.kategori && changes.kategori.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "K", changes.kategori); appliedAnything = true; } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { content = insertSenseWords(content, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); appliedAnything = true; } }); if (changes.subsection) { tryApply(function () { return insertPageSubsection(content, language, sectionType, sectionOrdinal, changes.subsection.def, changes.subsection.content); }); } if (!appliedAnything) { throw new SubmitAbort("Tiştek nehat guhertin."); } return { content: content, warnings: warnings }; } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the whole "guhartina pêşketî" panel into $quickRow: gloss (+ Oto-lînk bike) and the two // most-used word lists (Hevmane/Dijmane) sit directly in the picker row; the remaining SENSE_GROUPS word // lists, maneid, etîket, kategorî, and this POS block's own "+ beşek" subsection picker live behind a // single "Zêdetir" dropdown -- plus one shared Qeyd bike that saves everything the user actually filled // in as a single edit, via applyAdvancedChanges() and the shared saveChange() helper. Nimûne/jêgirtin // stays a separate, immediate proxy-click (see findExampleButton()) -- it opens a DIFFERENT gadget's own // form with its own independent save, so it can't be folded into this combined transform the way every // wikitext-writing field here can. function buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel) { var $nimune = $("<a href='#' class='dsb-quick-link'></a>").text("Nimûne/jêgirtin lê zêde bike"); $nimune.on("click", function (e) { e.preventDefault(); var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); // getters holds one function per currently-OPEN box (key -> () => value); collectChanges() below only // ever reads from a box the user actually clicked to add -- there is no "always all 11 fields present" // state any more (that was tried and reverted -- see this file's own history notes). var getters = {}; // -- gloss ("Maneyê biguhêre" -- the one box that EDITS the sense's own wording; everything else here // only ever ADDS to the definition line) -- function addGlossField() { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $status = $("<span class='dsb-status'></span>"); var originalGloss = null; fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { originalGloss = gloss; $textarea.val(gloss).prop("disabled", false); $autoLink.prop("disabled", false); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $status.text(""); }); }); getters.gloss = function () { var v = $.trim($textarea.val()); return (v && v !== originalGloss) ? v : null; }; return $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Mane"), $textarea, $("<div class='dsb-form-actions'></div>").append($autoLink, $status) ); } // -- one SENSE_GROUPS word-list box (Hevmane/Dijmane/etc.) -- function addWordField(group) { var field = buildWordListField(group.label + "…"); getters["word:" + group.key] = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text(group.label), field.$element); } // -- maneid (single value; re-adding one that already exists is rejected -- see applyAdvancedChanges) -- function addManeidField() { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); getters.maneid = function () { return $.trim($input.val()); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Nasnav (maneid)"), $input); } // -- etîket / kategorî -- function addEtiketField() { var field = buildTagField("Etîket…"); getters.etiket = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Etîket"), field.$element); } function addKategoriField() { var field = buildTagField("Kategorî…"); getters.kategori = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Kategorî"), field.$element); } // -- this POS block's own "====" subsections (same picker buildSubsectionPanel() uses, folded in here) -- function addSubsectionField() { var existingHeaders = existingSubsectionHeadersInDom($h3); var availableSubsections = PAGE_SUBSECTIONS.filter(function (s) { return existingHeaders.indexOf(s.header) === -1; }); var $wrap = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Beşek (====)")); if (!availableSubsections.length) { $wrap.append($("<div class='dsb-status'></div>").text("Hemû beş jixwe li vê hene.")); return $wrap; } var $select = $("<select class='dsb-subsection-select'></select>"); availableSubsections.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var subWordField = null; function currentSubsection() { var id = $select.val(); return availableSubsections.filter(function (s) { return s.id === id; })[0]; } function renderSubField() { var s = currentSubsection(); $fieldWrap.empty(); subWordField = null; if (s.kind === "wordlist") { subWordField = buildWordListField(s.header + "…"); $fieldWrap.append(subWordField.$element); } else { $fieldWrap.append($("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>").attr("placeholder", s.header + "…")); } } $select.on("change", renderSubField); renderSubField(); getters.subsection = function () { var s = currentSubsection(); var content = s.kind === "wordlist" ? subWordField.values() : $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); var hasContent = s.kind === "wordlist" ? content.length > 0 : content !== ""; return hasContent ? { def: s, content: content } : null; }; $wrap.append($select, $fieldWrap); return $wrap; } // -- the picker row: gloss + the two most-used word groups (Hevmane/Dijmane, same SENSE_GROUPS.primary // flag start.js itself uses to feature them) sit directly in the row; everything else (the remaining // word groups, maneid, etîket, kategorî, subsection) lives behind a single "Zêdetir" dropdown -- back to // the pre-round-12 layout the user actually wanted, on top of round 12's click-to-open-a-box mechanic: // clicking any link (primary or from the dropdown) builds and appends its box to $openBoxes and hides // that link; the box's own "×" removes it, clears its getter, and un-hides the link -- several boxes can // be open at once, unlike the old "only one form open at a time" behavior (round 3-10's $below). ---- var FIELD_DEFS = [{ key: "gloss", label: "Maneyê biguhêre", build: addGlossField, primary: true }] .concat(SENSE_GROUPS.map(function (group) { return { key: "word:" + group.key, label: group.label, build: function () { return addWordField(group); }, primary: !!group.primary }; })) .concat([ { key: "maneid", label: "Nasnav (maneid)", build: addManeidField, primary: false }, { key: "etiket", label: "Etîket", build: addEtiketField, primary: false }, { key: "kategori", label: "Kategorî", build: addKategoriField, primary: false }, { key: "subsection", label: "Beşek (====)", build: addSubsectionField, primary: false } ]); var $picker = $("<div class='dsb-field-picker'></div>"); var $moreMenu = $("<div class='dsb-more-menu'></div>").hide(); var $openBoxes = $("<div class='dsb-open-boxes'></div>"); FIELD_DEFS.forEach(function (def) { var $link = $("<a href='#' class='dsb-quick-link dsb-field-pick'></a>").text(def.key === "gloss" ? def.label : "+ " + def.label); $link.on("click", function (e) { e.preventDefault(); var $box = def.build(); var $remove = $("<a href='#' class='dsb-box-remove' title='Rake'>×</a>"); $remove.on("click", function (e2) { e2.preventDefault(); delete getters[def.key]; $box.remove(); $link.show(); }); $box.prepend($remove); $openBoxes.append($box); $link.hide(); $moreMenu.hide(); }); (def.primary ? $picker : $moreMenu).append($link); }); var $moreToggle = $("<a href='#' class='dsb-quick-link dsb-more-toggle'>Zêdetir</a>"); $moreToggle.on("click", function (e) { e.preventDefault(); $moreMenu.toggle(); }); $picker.append($moreToggle); // Closes the dropdown on an outside click, same as round 3-10's own "More" menu -- scoped to this // panel's own $moreToggle/$moreMenu, so it never touches another sense's panel. $(document).on("click", function (e) { if (!$(e.target).closest($moreToggle).length && !$(e.target).closest($moreMenu).length) { $moreMenu.hide(); } }); // -- combined save: whatever boxes are open right now, saved together via the shared saveChange() helper // (queues into window.editor when available, falls back to this file's own direct editPage() otherwise // -- see saveChange()'s own comment). ---- function collectChanges() { var words = {}; SENSE_GROUPS.forEach(function (group) { var getter = getters["word:" + group.key]; words[group.key] = getter ? getter() : []; }); return { gloss: getters.gloss ? getters.gloss() : null, maneid: getters.maneid ? getters.maneid() : "", etiket: getters.etiket ? getters.etiket() : [], kategori: getters.kategori ? getters.kategori() : [], words: words, subsection: getters.subsection ? getters.subsection() : null }; } var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); $cancel.on("click", function () { $quickRow.hide(); }); $save.on("click", function () { var changes = collectChanges(); function afterLinkify() { saveChange( "guhartina pêşketî (DefSideBoxes)", function (baseContent) { return applyAdvancedChanges(baseContent, language, sectionType, sectionOrdinal, definitionLevel, changes); }, $save, $status ); } $save.prop("disabled", true); // Same zero-links-gets-auto-linkified rule as every earlier round's gloss save -- only when the // gloss is actually part of this save, and only ever applied automatically when the user hasn't // already added a manual link themselves. if (changes.gloss && !/\[\[.+?\]\]/.test(changes.gloss)) { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(changes.gloss, function (linked) { changes.gloss = $.trim(linked); afterLinkify(); }); } else { afterLinkify(); } }); $quickRow.empty().append($nimune, $picker, $moreMenu, $openBoxes, $actions); } // Attaches the pencil toggle to one leaf definition <li> -- clicking it reveals the "guhartina pêşketî" // (advanced editing) panel built by buildAdvancedPanel() above: gloss/Hevmane/Dijmane sit as direct picker // links, everything else (the remaining SENSE_GROUPS word lists, maneid, etîket, kategorî, this POS // block's own subsections) behind a "Zêdetir" dropdown -- clicking any of them opens its own box, several // can be open at once, then one shared Qeyd bike saves everything currently open together, queued into the // real window.editor singleton when it's available and falling back to this file's own direct editPage() // otherwise (see saveChange()). function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Guhartina pêşketî'>✎</a>"); // Revealed by $toggle -- an indented panel under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. Built // lazily on first open (see buildAdvancedPanel()'s own fetchCurrentGloss() call) rather than eagerly // for every sense on the page. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); if ($quickRow.is(":visible") && !$quickRow.data("built")) { buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel); $quickRow.data("built", true); } }); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow); } else { $li.append($quickRow); } } // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); saveChange( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return { content: insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content), warnings: [] }; }, $save, $status ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Qeyd bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); saveChange( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return { content: convertManeToPos(pageContent, language, maneOrdinal, chosen), warnings: [] }; }, $save, $status ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); cnldqt0gqpv4ob8ouk8scqkcwmq2mb4 6347331 6347324 2026-08-31T10:22:35Z Wikihez 7344 6347331 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- this gadget's own save queue + floating widget ---- // Round 12/13 queued into the real "Gadget-Editor - kuwikt.js" singleton (window.editor) instead of saving // directly, so several DefSideBoxes edits could land in one save. That gadget turned out to be the wrong // vehicle for this: it's built around a different feature (queuing translation additions) and its own // floating widget shows a tip about that ("Tu dikarî hin wergerên din jî lê zêde bikî…") which makes no // sense next to a queued Hevmane/Dijmane/subsection change. This file now keeps its own small queue and its // own floating widget instead -- same "collect several edits, one real save" idea, but with UI that's // actually about what this gadget does. // // Each queued entry keeps its OWN transformFn rather than a pre-computed wikitext snapshot, so the real // save (saveQueueNow) can re-run every queued transform against freshly-fetched content in one // api.edit() transform -- same one-fetch, no-stale-overwrite pattern editPage() already uses everywhere // else in this file, just threaded through N transforms instead of one. var dsbQueue = { entries: [], // [{summary, transformFn}], transformFn: baseContent -> {content, warnings} previews: [] // [removeFn, ...] -- undoes every live DOM preview a queued entry added; see below }; var $queueBox = null; function registerPreview(removeFn) { dsbQueue.previews.push(removeFn); } function clearAllPreviews() { dsbQueue.previews.forEach(function (fn) { try { fn(); } catch (e) { /* a preview failing to clean up should never block the queue itself */ } }); dsbQueue.previews = []; } function clearQueue() { dsbQueue.entries = []; clearAllPreviews(); if ($queueBox) { $queueBox.$list.empty(); $queueBox.$box.hide(); } } function ensureQueueBox() { if ($queueBox) { return $queueBox; } var $box = $("<div class='dsb-queue-box'></div>").hide(); var $close = $("<a href='#' class='dsb-queue-close' title='Veşêre'>&#215;</a>"); var $title = $("<div class='dsb-queue-title'></div>").text("Guhertinên li benda qeydkirinê"); var $list = $("<ul class='dsb-queue-list'></ul>"); var $status = $("<div class='dsb-queue-status'></div>"); var $save = $("<button type='button' class='dsb-queue-save'>Guhertinan qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-queue-cancel'>Betal bike</button>"); var $actions = $("<div class='dsb-queue-actions'></div>").append($save, $cancel); $close.on("click", function (e) { e.preventDefault(); $box.hide(); }); $cancel.on("click", function () { clearQueue(); }); $save.on("click", function () { saveQueueNow(); }); $box.append($close, $title, $list, $actions, $status); $(document.body).append($box); $queueBox = { $box: $box, $list: $list, $status: $status, $save: $save, $cancel: $cancel }; return $queueBox; } function renderQueueBox() { var box = ensureQueueBox(); box.$list.empty(); dsbQueue.entries.forEach(function (entry) { box.$list.append($("<li></li>").text(entry.summary)); }); box.$status.removeClass("dsb-status-ok dsb-status-error").text(""); box.$save.prop("disabled", !dsbQueue.entries.length); box.$box.show(); } // The real save: re-runs every queued transformFn, in order, against ONE freshly-fetched revision (inside // editPage()'s own hardened transform) and posts the result as a single edit with a combined summary. function saveQueueNow() { if (!dsbQueue.entries.length) { return; } var box = ensureQueueBox(); box.$save.prop("disabled", true); box.$cancel.prop("disabled", true); box.$status.removeClass("dsb-status-ok dsb-status-error").text("Tê qeydkirin…"); var combinedSummary = dsbQueue.entries.map(function (entry) { return entry.summary; }).join("; "); editPage( combinedSummary, function (pageContent) { var content = pageContent; dsbQueue.entries.forEach(function (entry) { content = entry.transformFn(content).content; }); return content; }, function () { dsbQueue.entries = []; clearAllPreviews(); box.$list.empty(); box.$status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hemû guhertin hatin qeydkirin — rûpel nûve bike da ku bibînî."); box.$save.prop("disabled", true); box.$cancel.prop("disabled", false); }, function (message) { box.$save.prop("disabled", false); box.$cancel.prop("disabled", false); box.$status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } // Queues transformFn(baseWikitext) -> {content, warnings} for the real save to run later against fresh // content (see saveQueueNow()) -- nothing here touches the page yet, so a transform that would throw // SubmitAbort (e.g. "this subsection already exists") is only actually discovered when "Guhertinan qeyd // bike" runs it for real, same as queuing into a real editor would work. Also runs previewFn(), which a // caller uses to drop a small "not saved yet" preview into the live DOM at the change's own correct spot on // the page (see buildSubsectionPreviewDom() and the inline gloss/word-group preview in buildAdvancedPanel). // Shared by every panel that queues a wikitext change: buildAdvancedPanel, buildSubsectionPanel, // buildConvertPosPanel. function queueChange(summary, transformFn, $save, $status, previewFn) { dsbQueue.entries.push({ summary: summary, transformFn: transformFn }); $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text( "✓ li rêza guhertinan hate zêdekirin — pêl 'Guhertinan qeyd bike' li jorê bike da ku bicîh bibe." ); $save.prop("disabled", false); if (previewFn) { try { var removePreview = previewFn(); if (typeof removePreview === "function") { registerPreview(removePreview); } } catch (e) { /* a broken preview should never stop the change from being queued */ } } renderQueueBox(); } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- "guhartina pêşketî" (advanced editing): combine several independent per-sense edits into ONE save ---- // Threads pageContent through the same pure functions every single-field form already used // (updateSenseGloss/insertLeadingSenseTpl/insertSenseWords/insertPageSubsection), applying only the // pieces the caller actually filled in (see buildAdvancedPanel()'s own collectChanges()). A piece that // conflicts with something already on the page (maneid already set, a subsection that's already there) // is skipped with a warning rather than failing the whole save -- everything else the user changed still // goes through in the same edit. Throws SubmitAbort if literally nothing was filled in, so this can never // turn into a no-op save. function applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes) { var content = pageContent; var warnings = []; var appliedAnything = false; function tryApply(fn) { try { content = fn(); appliedAnything = true; } catch (e) { if (e instanceof SubmitAbort) { warnings.push(e.message); } else { throw e; } } } if (changes.gloss) { content = updateSenseGloss(content, language, sectionType, sectionOrdinal, definitionLevel, changes.gloss); appliedAnything = true; } if (changes.maneid) { tryApply(function () { return insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [changes.maneid], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }); } if (changes.etiket && changes.etiket.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "e", changes.etiket); appliedAnything = true; } if (changes.kategori && changes.kategori.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "K", changes.kategori); appliedAnything = true; } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { content = insertSenseWords(content, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); appliedAnything = true; } }); if (changes.subsection) { tryApply(function () { return insertPageSubsection(content, language, sectionType, sectionOrdinal, changes.subsection.def, changes.subsection.content); }); } if (!appliedAnything) { throw new SubmitAbort("Tiştek nehat guhertin."); } return { content: content, warnings: warnings }; } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the whole "guhartina pêşketî" panel into $quickRow: gloss (+ Oto-lînk bike) and the two // most-used word lists (Hevmane/Dijmane) sit directly in the picker row; the remaining SENSE_GROUPS word // lists, maneid, etîket, kategorî, and this POS block's own "+ beşek" subsection picker live behind a // single "Zêdetir" dropdown -- plus one shared "Lê zêde bike" that queues everything the user actually // filled in as a single edit, via applyAdvancedChanges() and the shared queueChange() helper (see this // file's own floating queue box, built by ensureQueueBox()). Nimûne/jêgirtin // stays a separate, immediate proxy-click (see findExampleButton()) -- it opens a DIFFERENT gadget's own // form with its own independent save, so it can't be folded into this combined transform the way every // wikitext-writing field here can. function buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel) { var $nimune = $("<a href='#' class='dsb-quick-link'></a>").text("Nimûne/jêgirtin lê zêde bike"); $nimune.on("click", function (e) { e.preventDefault(); var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } }); // getters holds one function per currently-OPEN box (key -> () => value); collectChanges() below only // ever reads from a box the user actually clicked to add -- there is no "always all 11 fields present" // state any more (that was tried and reverted -- see this file's own history notes). var getters = {}; // -- gloss ("Maneyê biguhêre" -- the one box that EDITS the sense's own wording; everything else here // only ever ADDS to the definition line) -- function addGlossField() { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $status = $("<span class='dsb-status'></span>"); var originalGloss = null; fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { originalGloss = gloss; $textarea.val(gloss).prop("disabled", false); $autoLink.prop("disabled", false); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $status.text(""); }); }); getters.gloss = function () { var v = $.trim($textarea.val()); return (v && v !== originalGloss) ? v : null; }; return $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Mane"), $textarea, $("<div class='dsb-form-actions'></div>").append($autoLink, $status) ); } // -- one SENSE_GROUPS word-list box (Hevmane/Dijmane/etc.) -- function addWordField(group) { var field = buildWordListField(group.label + "…"); getters["word:" + group.key] = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text(group.label), field.$element); } // -- maneid (single value; re-adding one that already exists is rejected -- see applyAdvancedChanges) -- function addManeidField() { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); getters.maneid = function () { return $.trim($input.val()); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Nasnav (maneid)"), $input); } // -- etîket / kategorî -- function addEtiketField() { var field = buildTagField("Etîket…"); getters.etiket = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Etîket"), field.$element); } function addKategoriField() { var field = buildTagField("Kategorî…"); getters.kategori = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Kategorî"), field.$element); } // -- this POS block's own "====" subsections (same picker buildSubsectionPanel() uses, folded in here) -- function addSubsectionField() { var existingHeaders = existingSubsectionHeadersInDom($h3); var availableSubsections = PAGE_SUBSECTIONS.filter(function (s) { return existingHeaders.indexOf(s.header) === -1; }); var $wrap = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Beşek (====)")); if (!availableSubsections.length) { $wrap.append($("<div class='dsb-status'></div>").text("Hemû beş jixwe li vê hene.")); return $wrap; } var $select = $("<select class='dsb-subsection-select'></select>"); availableSubsections.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var subWordField = null; function currentSubsection() { var id = $select.val(); return availableSubsections.filter(function (s) { return s.id === id; })[0]; } function renderSubField() { var s = currentSubsection(); $fieldWrap.empty(); subWordField = null; if (s.kind === "wordlist") { subWordField = buildWordListField(s.header + "…"); $fieldWrap.append(subWordField.$element); } else { $fieldWrap.append($("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>").attr("placeholder", s.header + "…")); } } $select.on("change", renderSubField); renderSubField(); getters.subsection = function () { var s = currentSubsection(); var content = s.kind === "wordlist" ? subWordField.values() : $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); var hasContent = s.kind === "wordlist" ? content.length > 0 : content !== ""; return hasContent ? { def: s, content: content } : null; }; $wrap.append($select, $fieldWrap); return $wrap; } // -- the picker row: gloss + the two most-used word groups (Hevmane/Dijmane, same SENSE_GROUPS.primary // flag start.js itself uses to feature them) sit directly in the row; everything else (the remaining // word groups, maneid, etîket, kategorî, subsection) lives behind a single "Zêdetir" dropdown -- back to // the pre-round-12 layout the user actually wanted, on top of round 12's click-to-open-a-box mechanic: // clicking any link (primary or from the dropdown) builds and appends its box to $openBoxes and hides // that link; the box's own "×" removes it, clears its getter, and un-hides the link -- several boxes can // be open at once, unlike the old "only one form open at a time" behavior (round 3-10's $below). ---- var FIELD_DEFS = [{ key: "gloss", label: "Maneyê biguhêre", build: addGlossField, primary: true }] .concat(SENSE_GROUPS.map(function (group) { return { key: "word:" + group.key, label: group.label, build: function () { return addWordField(group); }, primary: !!group.primary }; })) .concat([ { key: "maneid", label: "Nasnav (maneid)", build: addManeidField, primary: false }, { key: "etiket", label: "Etîket", build: addEtiketField, primary: false }, { key: "kategori", label: "Kategorî", build: addKategoriField, primary: false }, { key: "subsection", label: "Beşek (====)", build: addSubsectionField, primary: false } ]); var $picker = $("<div class='dsb-field-picker'></div>"); var $moreMenu = $("<div class='dsb-more-menu'></div>").hide(); var $openBoxes = $("<div class='dsb-open-boxes'></div>"); FIELD_DEFS.forEach(function (def) { var $link = $("<a href='#' class='dsb-quick-link dsb-field-pick'></a>").text(def.key === "gloss" ? def.label : "+ " + def.label); $link.on("click", function (e) { e.preventDefault(); var $box = def.build(); var $remove = $("<a href='#' class='dsb-box-remove' title='Rake'>×</a>"); $remove.on("click", function (e2) { e2.preventDefault(); delete getters[def.key]; $box.remove(); $link.show(); }); $box.prepend($remove); $openBoxes.append($box); $link.hide(); $moreMenu.hide(); }); (def.primary ? $picker : $moreMenu).append($link); }); var $moreToggle = $("<a href='#' class='dsb-quick-link dsb-more-toggle'>Zêdetir</a>"); $moreToggle.on("click", function (e) { e.preventDefault(); $moreMenu.toggle(); }); $picker.append($moreToggle); // Closes the dropdown on an outside click, same as round 3-10's own "More" menu -- scoped to this // panel's own $moreToggle/$moreMenu, so it never touches another sense's panel. $(document).on("click", function (e) { if (!$(e.target).closest($moreToggle).length && !$(e.target).closest($moreMenu).length) { $moreMenu.hide(); } }); // -- combined save: whatever boxes are open right now, queued together via the shared queueChange() // helper (see its own comment) -- the actual save happens later, when the user clicks "Guhertinan qeyd // bike" on this gadget's own floating queue box. ---- // Small "not saved yet" preview of everything this one queued change will do, appended right after // $quickRow (i.e. in the same spot the panel itself sits, right under the sense's gloss) -- plain text, // not a real render of {{hevmane}}/etc., but placed where the real content will actually end up once // the page is reloaded after a real save. function buildChangesPreview(changes) { var $prev = $("<div class='dsb-preview-inline'></div>"); $prev.append($("<span class='dsb-preview-badge'></span>").text("nû — hîn nehatiye qeydkirin")); var $list = $("<ul class='dsb-preview-list'></ul>"); function plain(w) { return w.replace(/<[^<>]*>/g, ""); } if (changes.gloss) { $list.append($("<li></li>").text("Mane: " + changes.gloss)); } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { $list.append($("<li></li>").text(group.label + ": " + words.map(plain).join(", "))); } }); if (changes.maneid) { $list.append($("<li></li>").text("Nasnav: " + changes.maneid)); } if (changes.etiket && changes.etiket.length) { $list.append($("<li></li>").text("Etîket: " + changes.etiket.join(", "))); } if (changes.kategori && changes.kategori.length) { $list.append($("<li></li>").text("Kategorî: " + changes.kategori.join(", "))); } if (changes.subsection) { $list.append($("<li></li>").text("+" + changes.subsection.def.header)); } $prev.append($list); return $prev; } function collectChanges() { var words = {}; SENSE_GROUPS.forEach(function (group) { var getter = getters["word:" + group.key]; words[group.key] = getter ? getter() : []; }); return { gloss: getters.gloss ? getters.gloss() : null, maneid: getters.maneid ? getters.maneid() : "", etiket: getters.etiket ? getters.etiket() : [], kategori: getters.kategori ? getters.kategori() : [], words: words, subsection: getters.subsection ? getters.subsection() : null }; } var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); $cancel.on("click", function () { $quickRow.hide(); }); $save.on("click", function () { var changes = collectChanges(); function afterLinkify() { queueChange( "guhartina pêşketî (DefSideBoxes)", function (baseContent) { return applyAdvancedChanges(baseContent, language, sectionType, sectionOrdinal, definitionLevel, changes); }, $save, $status, function () { var $prev = buildChangesPreview(changes); $quickRow.after($prev); return function () { $prev.remove(); }; } ); } $save.prop("disabled", true); // Same zero-links-gets-auto-linkified rule as every earlier round's gloss save -- only when the // gloss is actually part of this save, and only ever applied automatically when the user hasn't // already added a manual link themselves. if (changes.gloss && !/\[\[.+?\]\]/.test(changes.gloss)) { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(changes.gloss, function (linked) { changes.gloss = $.trim(linked); afterLinkify(); }); } else { afterLinkify(); } }); $quickRow.empty().append($nimune, $picker, $moreMenu, $openBoxes, $actions); } // Attaches the pencil toggle to one leaf definition <li> -- clicking it reveals the "guhartina pêşketî" // (advanced editing) panel built by buildAdvancedPanel() above: gloss/Hevmane/Dijmane sit as direct picker // links, everything else (the remaining SENSE_GROUPS word lists, maneid, etîket, kategorî, this POS // block's own subsections) behind a "Zêdetir" dropdown -- clicking any of them opens its own box, several // can be open at once, then one shared "Lê zêde bike" queues everything currently open together into this // gadget's own floating queue box (see queueChange()) -- the real save only happens when the user clicks // that box's own "Guhertinan qeyd bike". function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Guhartina pêşketî'>✎</a>"); // Revealed by $toggle -- an indented panel under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. Built // lazily on first open (see buildAdvancedPanel()'s own fetchCurrentGloss() call) rather than eagerly // for every sense on the page. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); if ($quickRow.is(":visible") && !$quickRow.data("built")) { buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel); $quickRow.data("built", true); } }); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow); } else { $li.append($quickRow); } } // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Finds where a NEW "====" subsection preview belongs in the live DOM, using the same canonical order // subsectionRankForHeader()/PAGE_SUBSECTIONS already give insertPageSubsection() for the real wikitext -- // so the preview shows up exactly where the real content will land after a save + reload, not just tacked // onto the end of the POS block. Returns either {insertBefore: $el} (an existing subsection that outranks // this one) or {insertAfter: $el} (nothing does -- goes at the end of the block). function domSubsectionInsertAnchor($h3, header) { var myRank = subsectionRankForHeader(header); var $last = headingOuter($h3); for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); var otherRank = subsectionRankForHeader($hh.text().trim()); if (otherRank !== -1 && otherRank > myRank) { return { insertBefore: $cursor }; } } $last = $cursor; } return { insertAfter: $last }; } // A small "not saved yet" preview of a page-level "====" subsection: a heading + its word list (or text), // dropped into the live page at its own canonical position (domSubsectionInsertAnchor()) so it reads as // "this is what will actually be here" rather than a form-panel status line. Plain text, not a real render // of {{kol3|...}}/etc. Returns the inserted element so the caller can remove it again (queue cancel, or // after a real save, when the page needs a reload to show the real thing anyway). function buildSubsectionPreviewDom($h3, s, content) { var $wrap = $("<div class='dsb-preview-block'></div>"); // A styled <div>, not a real <h4> -- existingSubsectionHeadersInDom() (".mw-heading4, h4") must never // mistake this live-only preview for an actual subsection already on the page, or a second "+ Beşek lê // zêde bike" would wrongly treat it as already there and hide it from the picker. $wrap.append($("<div class='dsb-preview-heading' role='heading' aria-level='4'></div>").text(s.header)); $wrap.append($("<span class='dsb-preview-badge'></span>").text("nû — hîn nehatiye qeydkirin")); if (s.kind === "wordlist") { var $list = $("<ul class='dsb-preview-list'></ul>"); content.forEach(function (w) { $list.append($("<li></li>").text(w.replace(/<[^<>]*>/g, ""))); }); $wrap.append($list); } else { $wrap.append($("<p class='dsb-preview-text'></p>").text(content)); } var anchor = domSubsectionInsertAnchor($h3, s.header); if (anchor.insertBefore) { anchor.insertBefore.before($wrap); } else { anchor.insertAfter.after($wrap); } return $wrap; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); queueChange( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return { content: insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content), warnings: [] }; }, $save, $status, function () { var $preview = buildSubsectionPreviewDom($h3, s, content); return function () { $preview.remove(); }; } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, $h3, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); queueChange( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return { content: convertManeToPos(pageContent, language, maneOrdinal, chosen), warnings: [] }; }, $save, $status, function () { // Preview: a small pending note right under the heading itself (its own correct spot on the // page), rather than rewriting the real heading text -- an in-place rewrite would need to be // reverted on failure/cancel but KEPT on a real success, and a real save failing partway // through would otherwise leave a real heading showing a name that was never actually saved. var $note = $("<div class='dsb-preview-inline dsb-preview-heading-note'></div>") .text("→ " + chosen + " — nû, hîn nehatiye qeydkirin"); headingOuter($h3).after($note); return function () { $note.remove(); }; } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, $h3, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); leqsof582rcxq84bnxmt6ft9vjz59xp 6347337 6347331 2026-08-31T11:07:49Z Wikihez 7344 6347337 javascript text/javascript // Gadget-DefSideBoxes.js // Per-definition and per-section quick-add toolbar for ku.wiktionary. // Full rewrite of en.wiktionary's Gadget-DefSideBoxes.js: that file depends on Editor/AdderWrapper/LangMetadata/ // util.validateNoWikisyntax and is hard-wired to en.wiktionary's senseid/sense/trans-top system and vector-only // hover positioning -- none of that fits ku.wiktionary. This version instead reuses the section/language-matching // helpers already proven (and twice bugfixed) in Gadget-wikt.add-examples.js, and writes ku.wiktionary's own // wikitext conventions (start.js's "#: {{hevmane|lang|...}}" per-sense lines and "{{kol3|...}}" page subsections). // Works on vector, vector2022 and minerva (mobile) -- no hover-only UI, no absolute positioning. // Dependencies: mediawiki.api, mediawiki.util, jquery. // Runtime coupling (not a declared ResourceLoader dependency): the "Nimûne/jêgirtin" menu item looks for the // button Gadget-wikt.add-examples.js already inserts on each definition, by its exact link text -- that gadget // must run first and must keep using the same text ("Nimûneyeke bikaranînê lê zêde bike"). // <nowiki> (function () { "use strict"; // Same namespace guard as Wiki/start.js and Gadget-wikt.add-examples.js: main namespace, namespace 108 // (used for reconstructed-entry pages -- see start.js's own "{{jinûvesazkirî|...}}" handling), or a // user's own /ceribandin or /test sandbox subpage. if (mw.config.get("wgAction") !== "view") { return; } var ns = mw.config.get("wgNamespaceNumber"); if (ns && ns !== 108 && !(ns === 2 && mw.config.get("wgPageName").match(/\/ceribandin$|\/test$/))) { return; } if (/&printable=yes|&diff=|&oldid=/.test(window.location.search)) { return; } window.wikt = window.wikt || {}; if (window.wikt.defSideBoxesLoaded) { return; } window.wikt.defSideBoxesLoaded = true; var api = new mw.Api(); // Recognized part-of-speech section headings -- keep in sync with Gadget-wikt.add-examples.js's own copy. var sectionNames = { "Navdêr": ["Navdêr"], "Formeke navdêrê": ["Formeke navdêrê"], "Lêker": ["Lêker"], "Formeke lêkerê": ["Formeke lêkerê"], "Rengdêr": ["Rengdêr"], "Formeke rengdêrê": ["Formeke rengdêrê"], "Hoker": ["Hoker"], "Formeke hokerê": ["Formeke hokerê"], "Serenav": ["Serenav"], "Formeke serenavê": ["Formeke serenavê"], "Artîkel": ["Artîkel"], "Baneşan": ["Baneşan"], "Bazinedaçek": ["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"] }; // The six per-sense groups start.js writes as "#: {{tpl|lang|word1|word2}}" sub-lines under a "#" definition. // Order matters only for where a brand-new group line lands relative to other existing group lines. // "primary: true" groups get their own always-visible quick link on the definition (mirrors // en.wiktionary's own DefSideBoxes, which keeps "+Add example sentence"/"+Add quotation" always visible // and tucks everything else behind "More"); the rest live inside this gadget's own "More" menu instead. var SENSE_GROUPS = [ { key: "alt-r", label: "Formek alternatîv" }, { key: "hevmane", label: "Hevmane", primary: true }, { key: "dijmane", label: "Dijmane", primary: true }, { key: "koordîne", label: "Termek koordîne" }, { key: "jornav", label: "Jornav" }, { key: "jêrnav", label: "Jêrnav" } ]; // Page-level (per part-of-speech, "====" heading) subsections start.js can also build from scratch. // "kind: wordlist" ones use {{kol3|lang|cure=Header|word1|word2}}; "kind: text" ones are a plain paragraph. // Dûnde is left out here -- its wikitext is a multi-language table, not yet ported. // Order here IS the canonical ku.wiktionary entry-layout order for "====" subsections (the user's own // full list runs Bilêvkirin, Ji wêjeya klasîk, Ji wêjeyê, Tewandin, Notên bikaranînê, Bi alfabeyên din, // Formên alternatîv, Kurtkirin, Sembol, Navê zanistî, Hevmane, Nêzîk, Dijmane, Jornav, Jêrnav, Jê, // Têkildar, Etîmolojî, Dûnde, Bide ber, Herwiha binêre, Bêhtir bixwîne, Bi zaravayên din, Werger, Qafiye, // Anagram, Çavkanî) -- only the steps with a confirmed wikitext format are implemented here. Left out for // now: Bilêvkirin (a "===" section per language in start.js, not a "====" subsection inside a POS block -- // doesn't fit this array's model at all); Dûnde/Bi zaravayên din/Werger (start.js implements these, but as // genuinely complex multi-language table sections, same reason they were deferred in earlier rounds); Ji // wêjeya klasîk, Ji wêjeyê, Kurtkirin, Sembol, Navê zanistî, Nêzîk, Bide ber, Qafiye, Anagram (no // confirmed wikitext format anywhere in start.js -- adding these would mean inventing templates for a // tool that edits live pages). insertPageSubsection() uses this array's own order as the insertion rank // -- see subsectionRankForHeader(). var PAGE_SUBSECTIONS = [ { id: "tewandin", header: "Tewandin", kind: "text" }, { id: "bikaranin", header: "Notên bikaranînê", kind: "text" }, { id: "alfabeyendin", header: "Bi alfabeyên din", kind: "text" }, { id: "formalt", header: "Formên alternatîv", kind: "wordlist" }, { id: "hevmane", header: "Hevmane", kind: "wordlist" }, { id: "dijmane", header: "Dijmane", kind: "wordlist" }, { id: "jornav", header: "Jornav", kind: "wordlist" }, { id: "jernav", header: "Jêrnav", kind: "wordlist" }, { id: "je", header: "Jê", kind: "wordlist" }, { id: "tekildar", header: "Têkildar", kind: "wordlist" }, { id: "etym", header: "Etîmolojî", kind: "text" }, { id: "binereherwiha", header: "Herwiha binêre", kind: "wordlist" }, { id: "xwendin", header: "Bêhtir bixwîne", kind: "text" }, { id: "cavkani", header: "Çavkanî", kind: "text" } ]; // ---- word-modifier system, ported from start.js's own makeModifierLi()/WORD_MODIFIERS (the exact widget // start.js uses for Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav, both as a page-level // {{kol3|...}} list and as a per-sense "#: {{tpl|lang|...}}" line) -- every word in one of these lists can // carry small "<key:value>" annotations (translation, gender, label, ...), which the {{hevmane}}/{{kol3}}/etc. // templates parse back out of the raw positional param. A word with no annotations is just its plain text. var WORD_MODIFIERS = [ { key: "t", label: "t: tercime / îzah", hint: "Tercimeya kelîmeyê an îzaha wê" }, { key: "cuda", label: "cuda: alt display", hint: "Forma nîşankirinê ya alternatîv" }, { key: "c", label: "c: cinsiyet", hint: "Cinsiyeta kelîmeyê" }, { key: "e", label: "e: etîket (li pêşiyê)", hint: "Etîketek li pêşiya kelîmeyê" }, { key: "ee", label: "ee: etîket (li dawiyê)", hint: "Etîketek li dawiya kelîmeyê" }, { key: "q", label: "q: wesf (li pêşiyê)", hint: "Wesf li pêşiya kelîmeyê" }, { key: "qq", label: "qq: wesf (li dawiyê)", hint: "Wesf li dawiya kelîmeyê" }, { key: "crz", label: "crz: cureyê rêzimanî", hint: "Cureyê rêzimanî yê kelîmeyê" }, { key: "hrf", label: "hrf: herfiyen", hint: "Herfiyen, manaya rasterast" }, { key: "ref", label: "ref: çavkanî", hint: "Çavkanî" } ]; // Short "key: value" prefix each modifier gets in its pill's display label -- keyed the same as WORD_MODIFIERS. var WORD_MODIFIER_DISPLAY_PREFIX = { t: "tercime: ", cuda: "cuda: ", c: "cinsiyet: ", e: "etîket: ", ee: "etîket: ", q: "wesf: ", qq: "wesf: ", crz: "cureyê rêzimanî: ", hrf: "herfiyen: ", ref: "çavkanî: " }; /** "key: value" chip label for one attached modifier. */ function modChipLabel(mo) { var prefix = WORD_MODIFIER_DISPLAY_PREFIX[mo.key]; return (prefix === undefined ? mo.key + ": " : prefix) + mo.value; } /** Joins a word plus its attached modifiers back into the raw "word<key:value>…" form the {{hevmane}}/ * {{kol3}}/etc. templates read. No re-hydration path is needed here (unlike start.js's own form, this * panel is never pre-filled from existing page content) so there is no matching parseWordValue(). */ function joinWordValue(word, mods) { if (!word) { return ""; } var out = word; mods.forEach(function (mo) { out += "<" + mo.key + ":" + mo.value + ">"; }); return out; } // ---- section/language helpers, ported from Gadget-wikt.add-examples.js (same document-order technique, so // mobile's per-section DOM wrapping and MediaWiki's page-wide heading-id collisions can't break it) ---- // MediaWiki wraps each heading in a "mw-heading2/3/.../" div in current skin output. function headingOuter($h) { var $wrap = $h.closest(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6"); return $wrap.length ? $wrap : $h; } // Section's language code: nearest preceding .besazimani[id] by document order, not sibling-walking. function languageCodeForOl($ol) { var $marks = $(".besazimani[id]").add($ol); var ol = $ol.get(0); var idx = $marks.index(ol); for (var i = idx - 1; i >= 0; i--) { var el = $marks.get(i); if (el.id) { return el.id; } } return null; } // Canonical section-type key for a heading, stripping a page author's own disambiguating trailing number. function sectionTypeOf($h3) { var text = $h3.text().trim(); if (sectionNames[text]) { return text; } var stripped = text.replace(/\s+\d+$/, ""); return sectionNames[stripped] ? stripped : null; } // This heading's 1-based position among same-type headings within its own language block. function sectionOrdinalWithinLanguage($h3) { var h3El = $h3.get(0); var $all = $(".besazimani[id]").add($("h3")); var counts = {}; var result = 1; $all.each(function () { if ($(this).is(".besazimani[id]")) { counts = {}; return; } var type = sectionTypeOf($(this)) || $(this).text().trim(); counts[type] = (counts[type] || 0) + 1; if (this === h3El) { result = counts[type]; return false; } }); return result; } // A "form of"-template-generated <li> wraps its own content; its nested <ol> isn't real "##" senses. function isFormOfWrapper($li) { return $li.children(".form-of-definition").length > 0; } // Recurse into a <li>'s nested <ol> unless it's a form-of wrapper. function eachLeafDefinition($ol, fn) { $ol.children("li").each(function () { var $li = $(this); var $childOl = $li.children("ol"); if ($childOl.length && !isFormOfWrapper($li)) { $childOl.each(function () { eachLeafDefinition($(this), fn); }); } else { fn($li); } }); } // ---- small shared utilities ---- // Escapes str for safe interpolation into a RegExp. function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // Extracts a human-readable message from an mw.Api rejection. function apiErrorMessage(code, result) { return (result && result.error && result.error.info) || (typeof code === "string" ? code : "Xeletiyeke nenas"); } // Thrown from inside an edit() transform to bail out with a specific message, not a generic API failure. function SubmitAbort(message) { this.message = message; } // Runs transformFn(content) inside mw.Api().edit()'s own transform callback -- one fetch covers both the // edit-conflict check and the content, matching the hardened pattern in Gadget-wikt.add-examples.js // (an earlier separate-fetch version could silently overwrite someone else's edit landed in between). function editPage(summary, transformFn, onSuccess, onError) { api.edit(mw.config.get("wgPageName"), function (revision) { return { text: transformFn(revision.content), summary: summary }; }).then(onSuccess, function (codeOrAbort, result) { if (codeOrAbort instanceof SubmitAbort) { onError(codeOrAbort.message); } else { onError("Nekarî rûpelê xilas bike: " + apiErrorMessage(codeOrAbort, result)); } }); } // ---- this gadget's own save queue + floating widget ---- // Round 12/13 queued into the real "Gadget-Editor - kuwikt.js" singleton (window.editor) instead of saving // directly, so several DefSideBoxes edits could land in one save. That gadget turned out to be the wrong // vehicle for this: it's built around a different feature (queuing translation additions) and its own // floating widget shows a tip about that ("Tu dikarî hin wergerên din jî lê zêde bikî…") which makes no // sense next to a queued Hevmane/Dijmane/subsection change. This file now keeps its own small queue and its // own floating widget instead -- same "collect several edits, one real save" idea, but with UI that's // actually about what this gadget does. // // Each queued entry keeps its OWN transformFn rather than a pre-computed wikitext snapshot, so the real // save (saveQueueNow) can re-run every queued transform against freshly-fetched content in one // api.edit() transform -- same one-fetch, no-stale-overwrite pattern editPage() already uses everywhere // else in this file, just threaded through N transforms instead of one. var dsbQueue = { entries: [], // [{summary, transformFn}], transformFn: baseContent -> {content, warnings} previews: [] // [removeFn, ...] -- undoes every live DOM preview a queued entry added; see below }; var $queueBox = null; function registerPreview(removeFn) { dsbQueue.previews.push(removeFn); } function clearAllPreviews() { dsbQueue.previews.forEach(function (fn) { try { fn(); } catch (e) { /* a preview failing to clean up should never block the queue itself */ } }); dsbQueue.previews = []; } function clearQueue() { dsbQueue.entries = []; clearAllPreviews(); if ($queueBox) { $queueBox.$list.empty(); $queueBox.$box.hide(); } } function ensureQueueBox() { if ($queueBox) { return $queueBox; } var $box = $("<div class='dsb-queue-box'></div>").hide(); var $close = $("<a href='#' class='dsb-queue-close' title='Veşêre'>&#215;</a>"); var $title = $("<div class='dsb-queue-title'></div>").text("Guhertinên li benda qeydkirinê"); var $list = $("<ul class='dsb-queue-list'></ul>"); var $status = $("<div class='dsb-queue-status'></div>"); var $save = $("<button type='button' class='dsb-queue-save'>Guhertinan qeyd bike</button>"); var $cancel = $("<button type='button' class='dsb-queue-cancel'>Betal bike</button>"); var $actions = $("<div class='dsb-queue-actions'></div>").append($save, $cancel); $close.on("click", function (e) { e.preventDefault(); $box.hide(); }); $cancel.on("click", function () { clearQueue(); }); $save.on("click", function () { saveQueueNow(); }); $box.append($close, $title, $list, $actions, $status); $(document.body).append($box); $queueBox = { $box: $box, $list: $list, $status: $status, $save: $save, $cancel: $cancel }; return $queueBox; } function renderQueueBox() { var box = ensureQueueBox(); box.$list.empty(); dsbQueue.entries.forEach(function (entry) { box.$list.append($("<li></li>").text(entry.summary)); }); box.$status.removeClass("dsb-status-ok dsb-status-error").text(""); box.$save.prop("disabled", !dsbQueue.entries.length); box.$box.show(); } // The real save: re-runs every queued transformFn, in order, against ONE freshly-fetched revision (inside // editPage()'s own hardened transform) and posts the result as a single edit with a combined summary. function saveQueueNow() { if (!dsbQueue.entries.length) { return; } var box = ensureQueueBox(); box.$save.prop("disabled", true); box.$cancel.prop("disabled", true); box.$status.removeClass("dsb-status-ok dsb-status-error").text("Tê qeydkirin…"); var combinedSummary = dsbQueue.entries.map(function (entry) { return entry.summary; }).join("; "); editPage( combinedSummary, function (pageContent) { var content = pageContent; dsbQueue.entries.forEach(function (entry) { content = entry.transformFn(content).content; }); return content; }, function () { dsbQueue.entries = []; clearAllPreviews(); box.$list.empty(); box.$status.removeClass("dsb-status-error").addClass("dsb-status-ok").text("✓ hemû guhertin hatin qeydkirin — rûpel nûve bike da ku bibînî."); box.$save.prop("disabled", true); box.$cancel.prop("disabled", false); }, function (message) { box.$save.prop("disabled", false); box.$cancel.prop("disabled", false); box.$status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); } // Queues transformFn(baseWikitext) -> {content, warnings} for the real save to run later against fresh // content (see saveQueueNow()) -- nothing here touches the page yet, so a transform that would throw // SubmitAbort (e.g. "this subsection already exists") is only actually discovered when "Guhertinan qeyd // bike" runs it for real, same as queuing into a real editor would work. Also runs previewFn(), which a // caller uses to drop a small "not saved yet" preview into the live DOM at the change's own correct spot on // the page (see buildSubsectionPreviewDom() and the inline gloss/word-group preview in buildAdvancedPanel). // Shared by every panel that queues a wikitext change: buildAdvancedPanel, buildSubsectionPanel, // buildConvertPosPanel. function queueChange(summary, transformFn, $save, $status, previewFn) { dsbQueue.entries.push({ summary: summary, transformFn: transformFn }); $status.removeClass("dsb-status-error").addClass("dsb-status-ok").text( "✓ li rêza guhertinan hate zêdekirin — pêl 'Guhertinan qeyd bike' li jorê bike da ku bicîh bibe." ); $save.prop("disabled", false); if (previewFn) { try { var removePreview = previewFn(); if (typeof removePreview === "function") { registerPreview(removePreview); } } catch (e) { /* a broken preview should never stop the change from being queued */ } } renderQueueBox(); } // Runs text through the ext.gadget.linkify gadget (start.js's own linkifyText()/$.kuLinkify -- the real, // already-deployed word-linking logic; see its own Wiki/linkify.js for what it actually does) and calls // back with the linkified result. Passes the text through unchanged if the gadget can't be loaded, same // fallback start.js's own linkifyText() uses -- never blocks a save on it. function linkifyText(text, cb) { function run() { if (typeof $.kuLinkify === "function") { $.kuLinkify(text, cb); } else { cb(text); } } mw.loader.using("ext.gadget.linkify", run, run); } // ---- wikitext location, ported/adapted from Gadget-wikt.add-examples.js's own submit() ---- // Bounds the language section as line indices into pageContent.split("\n"), and finds the matching POS // heading's own line index within that range by sectionType+ordinal -- never by a DOM id number, which // MediaWiki's page-wide anchor uniquification can attach to a heading for reasons unrelated to its actual // position (see Gadget-wikt.add-examples.js's own bugfix history for why that broke on a real page). function locateSection(pageContent, language, sectionType, sectionOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; if (!sectionNames[sectionType]) { throw new SubmitAbort("Navê beşê xelet e."); } // lines covers the WHOLE rest of the page from this language's heading onward, since the caller // reuses it to rebuild the entire saved text -- only the section-heading search itself is bounded // (via sectionSearchEndLine), so a same-named heading in a later language can never match by mistake. var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var sectionNamesRegex = Object.keys(sectionNames).join("|"); var sectionRegex = new RegExp("^===[ ]*(" + sectionNamesRegex + ")\\s*(\\d+)?"); var posLineIndex; var occurrence = 0; for (posLineIndex = 0; posLineIndex < sectionSearchEndLine; posLineIndex++) { var m = sectionRegex.exec(lines[posLineIndex]); if (m && sectionNames[sectionType].indexOf(m[1]) !== -1) { occurrence++; if (occurrence === sectionOrdinal) { break; } } } if (posLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Di navê beşê de xeletî heye. Îhtimalen bi vî navê beşê çend heb hene."); } return { langSectionIndex: langSectionIndex, lines: lines, posLineIndex: posLineIndex }; } // Walks "#"-prefixed lines from posLineIndex to find the exact line for definitionLevel -- an array whose // element 0 is unused here (it's the "type|ordinal" string locateSection already resolved) and whose // remaining elements are 0-based indices, one per nesting level (see eachLeafDefinition's own construction). function findDefinitionLine(lines, posLineIndex, definitionLevel) { var defIndex = -1; var level = 1; for (var i = posLineIndex; i < lines.length; i++) { var m = /^(#+)[^*#:]/.exec(lines[i]); if (m && m[1].length === level) { defIndex++; if (definitionLevel[level] === defIndex) { if (level === definitionLevel.length - 1) { return i; } level++; defIndex = -1; } } } throw new SubmitAbort("Nikarî rêza vê maneyê di nivîsê de bibîne."); } // Inserts or extends a "#: {{tplKey|lang|word1|word2}}" sub-line for one sense (start.js's own wordLine() // format). If a line for this same tplKey already exists under the definition, missing words are appended // to it instead of adding a duplicate line; otherwise a new line lands after the last existing group line // (or right after the definition itself), always before any "#*"/citation lines, matching start.js's order. function insertSenseWords(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, words) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = new Array(definitionLevel.length).join("#"); // definitionLevel.length - 1 "#" characters var tplLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*" + escapeRegExp(tplKey) + "\\s*\\|([^}]*)\\}\\}\\s*$"); var groupKeysPattern = SENSE_GROUPS.map(function (g) { return escapeRegExp(g.key); }).join("|"); var groupLineRegex = new RegExp("^" + marker + ":\\s*\\{\\{\\s*(" + groupKeysPattern + ")\\s*\\|"); var anyBlockLineRegex = new RegExp("^" + marker + "[:*]"); var lastGroupLine = -1; for (var i = defLine + 1; i < lines.length; i++) { if (!anyBlockLineRegex.test(lines[i])) { break; } var tplMatch = tplLineRegex.exec(lines[i]); if (tplMatch) { var params = tplMatch[1].split("|"); // [lang, word1, word2, ...] var existingWords = params.slice(1); words.forEach(function (w) { if (existingWords.indexOf(w) === -1) { existingWords.push(w); } }); lines[i] = marker + ": {{" + tplKey + "|" + language + "|" + existingWords.join("|") + "}}"; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } if (groupLineRegex.test(lines[i])) { lastGroupLine = i; } } var insertAt = lastGroupLine >= 0 ? lastGroupLine + 1 : defLine + 1; lines.splice(insertAt, 0, marker + ": {{" + tplKey + "|" + language + "|" + words.join("|") + "}}"); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Canonical left-to-right order of the small templates that can prefix a definition line's own gloss // text -- start.js itself only ever builds "{{K|lang|...}} {{e|lang|...}} <gloss>" (kategori before // etîket; Dever/Şîve, which would sit between them, is out of scope here); maneid is placed first, // matching the user's own live example ("{{maneid|ku|id}} {{f|ku|id}} <gloss>"). var LEADING_TPL_ORDER = ["maneid", "K", "e"]; // Parses the leading run of "{{...}}" calls off the front of a definition line's text-after-marker // (maneid/K/e in whatever order they're already in, plus any other template already there, e.g. a form-of // call) -- stops at the first thing that isn't one, normally the gloss text itself. Shared by // insertLeadingSenseTpl() (which searches "calls" for an existing tplKey to extend or insert next to) and // updateSenseGloss()/fetchCurrentGloss() (which only care about "rest", the gloss text after every call). function splitLeadingCalls(afterMarker) { var calls = []; var rest = afterMarker; var leadingRegex = /^\{\{\s*([^{}|]+?)\s*\|([^{}]*)\}\}\s*/; var m; while ((m = leadingRegex.exec(rest)) !== null) { calls.push({ key: m[1], params: m[2].split("|") }); rest = rest.slice(m[0].length); } return { calls: calls, rest: rest }; } // Inserts (or, unless opts.noExtend, extends) one of the small templates that prefix a definition // line's own gloss text -- {{maneid|lang|id}}, {{K|lang|kat1|...}} (kategori) or {{e|lang|etîket1|...}} // (etîket). Extending merges new values into an existing call the same way insertSenseWords() does for // "#:" sub-lines; opts.noExtend instead aborts if the template is already there (used for maneid, which // identifies the sense and so must never silently get a second, different id). function insertLeadingSenseTpl(pageContent, language, sectionType, sectionOrdinal, definitionLevel, tplKey, values, opts) { opts = opts || {}; var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); // Collecting the WHOLE leading-call run (not just tplKey's own regex against position 0) means an // existing tplKey call is found and merged wherever it already sits, not just when it happens to be // first. var split = splitLeadingCalls(afterMarker); var calls = split.calls; var rest = split.rest; var existing = null; calls.forEach(function (c) { if (c.key === tplKey) { existing = c; } }); if (existing) { if (opts.noExtend) { throw new SubmitAbort("Ev hevok jixwe xwedan " + (opts.noExtendLabel || tplKey) + " e."); } var existingVals = existing.params.slice(1); values.forEach(function (v) { if (existingVals.indexOf(v) === -1) { existingVals.push(v); } }); existing.params = [language].concat(existingVals); } else { // Not present yet -- insert right before the first existing call that outranks tplKey in // LEADING_TPL_ORDER (an unrecognized call, e.g. a form-of template, always outranks everything), // or at the end of the run if every existing call comes before tplKey. var myRank = LEADING_TPL_ORDER.indexOf(tplKey); var insertAt = calls.length; for (var i = 0; i < calls.length; i++) { var otherRank = LEADING_TPL_ORDER.indexOf(calls[i].key); if (otherRank === -1 || otherRank > myRank) { insertAt = i; break; } } calls.splice(insertAt, 0, { key: tplKey, params: [language].concat(values) }); } var rebuilt = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (rebuilt ? rebuilt + " " : "") + rest; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Replaces just the gloss text of a definition line, leaving any leading "{{maneid|...}}"/"{{K|...}}"/ // "{{e|...}}"/other template calls exactly as they were -- the save half of "Maneyê biguhêre" (edit sense). function updateSenseGloss(pageContent, language, sectionType, sectionOrdinal, definitionLevel, newGloss) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var defLine = findDefinitionLine(lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(lines[defLine])[0]; var afterMarker = lines[defLine].slice(marker.length).replace(/^\s+/, ""); var calls = splitLeadingCalls(afterMarker).calls; // "{{mane?|lang}}" is start.js's own "no definition entered yet" placeholder (see steps.dfn's own // getOutput()) -- once the user provides a real gloss through this form, that placeholder is fully // replaced, never kept alongside the new text the way maneid/K/e/etc. (real metadata) are. calls = calls.filter(function (c) { return c.key !== "mane?"; }); var leadingText = calls.map(function (c) { return "{{" + c.key + "|" + c.params.join("|") + "}}"; }).join(" "); lines[defLine] = marker + " " + (leadingText ? leadingText + " " : "") + newGloss; return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // Fetches the page's current wikitext and pulls out just this sense's gloss text (splitLeadingCalls().rest) // to prefill the "Maneyê biguhêre" form. A plain read, not part of the hardened save path -- the actual // save still runs updateSenseGloss() inside editPage()'s own transform against freshly-fetched content, so // someone else's edit landing between this read and that save can never be silently overwritten; only the // prefilled text itself could be a little stale, same as any edit form built from a page you loaded earlier. function fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel) { return api.get({ action: "query", prop: "revisions", rvprop: "content", titles: mw.config.get("wgPageName"), formatversion: 2 }).then(function (data) { var page = data.query && data.query.pages && data.query.pages[0]; var content = page && !page.missing && page.revisions && page.revisions[0] && page.revisions[0].content; if (!content) { throw new SubmitAbort("Nikarî muhtewaya rûpelê bixwîne."); } var loc = locateSection(content, language, sectionType, sectionOrdinal); var defLine = findDefinitionLine(loc.lines, loc.posLineIndex, definitionLevel); var marker = /^#+/.exec(loc.lines[defLine])[0]; var afterMarker = loc.lines[defLine].slice(marker.length).replace(/^\s+/, ""); return splitLeadingCalls(afterMarker).rest; }); } // Finds a POS block's own body range (its "===" line's own index up to, but not including, the next // heading of level <= 3), and the header text + line index of any "====" subsections it already contains // (the line index lets insertPageSubsection() splice a new subsection in right before an existing one, // not just always at the very end). function posBlockBounds(lines, posLineIndex) { var end = lines.length; var existingHeaders = []; for (var i = posLineIndex + 1; i < lines.length; i++) { if (/^===[^=]/.test(lines[i]) || /^==[^=]/.test(lines[i])) { end = i; break; } var h4 = /^====\s*([^=]+?)\s*====/.exec(lines[i]); if (h4) { existingHeaders.push({ header: h4[1].trim(), lineIndex: i }); } } return { end: end, existingHeaders: existingHeaders }; } // PAGE_SUBSECTIONS' own array order IS the canonical ku.wiktionary subsection order (see its own comment) -- // this just looks up a header's rank in it. -1 for a header that isn't one of ours (hand-authored, or a // convention step this gadget doesn't support yet); such a header is never used as an insertion anchor. function subsectionRankForHeader(header) { for (var i = 0; i < PAGE_SUBSECTIONS.length; i++) { if (PAGE_SUBSECTIONS[i].header === header) { return i; } } return -1; } // Inserts a new "==== Header ====" subsection into its canonical position within a POS block (right before // the first EXISTING recognized subsection that outranks it -- same "leading run" idea as // LEADING_TPL_ORDER/insertLeadingSenseTpl, just for whole ==== blocks instead of {{...}} calls on one // line), falling back to the end of the block when nothing there outranks it. Either a {{kol3|...}} word // list (start.js's makeWordListStep format) or a plain paragraph, matching start.js's other custom steps // (Etîmolojî, Notên bikaranînê, ...). function insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, subsection, content) { var loc = locateSection(pageContent, language, sectionType, sectionOrdinal); var lines = loc.lines; var bounds = posBlockBounds(lines, loc.posLineIndex); var alreadyThere = false; bounds.existingHeaders.forEach(function (h) { if (h.header === subsection.header) { alreadyThere = true; } }); if (alreadyThere) { throw new SubmitAbort("Ev beş jixwe heye: " + subsection.header); } var block; if (subsection.kind === "wordlist") { var params = "cure=" + subsection.header + "\n" + content.map(function (w) { return "|" + w; }).join("\n"); block = "\n==== " + subsection.header + " ====\n{{kol3|" + language + "|" + params + "\n}}\n"; } else { block = "\n==== " + subsection.header + " ====\n" + content + "\n"; } var myRank = subsectionRankForHeader(subsection.header); var insertAt = bounds.end; for (var i = 0; i < bounds.existingHeaders.length; i++) { var otherRank = subsectionRankForHeader(bounds.existingHeaders[i].header); if (otherRank !== -1 && otherRank > myRank) { insertAt = bounds.existingHeaders[i].lineIndex; break; } } lines.splice(insertAt, 0, block); return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- converting an unclassified "=== Mane ===" placeholder heading into a real POS heading ---- // Some pages carry a heading literally named "Mane" (optionally "Mane 2" etc. if more than one collides) // instead of a real part-of-speech name, tagged right below with {{cure?|<lang>}} -- ku.wiktionary's own // "cureyê rêzimanî nediyar e" (part of speech not yet determined) maintenance flag. Neither is in // sectionNames, so sectionTypeOf() and locateSection() never match it; these two functions are a small // parallel path just for finding/rewriting that one placeholder heading. // Same document-position technique as locateSection(), but matches the literal "Mane" heading text (plus // an optional page author's own disambiguating trailing number) instead of a recognized POS name. function locateManeSection(pageContent, language, maneOrdinal) { var langSectionRegex = new RegExp("==[ ]*\\{\\{ziman\\|" + escapeRegExp(language) + "\\}\\}[ ]*=="); var langSectionIndex = pageContent.search(langSectionRegex); if (langSectionIndex === -1) { throw new SubmitAbort("Xeletiyeke bi koda zimanî heye. Koda zimanî: " + language); } var afterLangHeading = pageContent.indexOf("\n", langSectionIndex); afterLangHeading = afterLangHeading === -1 ? pageContent.length : afterLangHeading + 1; var nextLangSectionMatch = /\n==[^=\n][^\n]*==/.exec(pageContent.slice(afterLangHeading)); var langSectionEnd = nextLangSectionMatch ? afterLangHeading + nextLangSectionMatch.index : pageContent.length; var lines = pageContent.slice(langSectionIndex).split("\n"); var sectionSearchEndLine = pageContent.slice(langSectionIndex, langSectionEnd).split("\n").length; var maneRegex = /^===[ ]*Mane(\s+\d+)?[ ]*===/; var maneLineIndex; var occurrence = 0; for (maneLineIndex = 0; maneLineIndex < sectionSearchEndLine; maneLineIndex++) { if (maneRegex.test(lines[maneLineIndex])) { occurrence++; if (occurrence === maneOrdinal) { break; } } } if (maneLineIndex === sectionSearchEndLine) { throw new SubmitAbort("Beşa 'Mane' ya nediyarkirî li ser rûpelê nehat dîtin. Dibe ku rûpel hatibe guhertin."); } return { langSectionIndex: langSectionIndex, lines: lines, maneLineIndex: maneLineIndex }; } // Renames the "=== Mane ===" placeholder to the chosen POS heading and drops the {{cure?|...}} line right // after it, if present -- that template flags "part of speech not yet determined", which no longer holds // once a real one is chosen. Any other content under the heading (the "#" senses, subsections, ...) is // left untouched. function convertManeToPos(pageContent, language, maneOrdinal, newSectionType) { if (!sectionNames[newSectionType]) { throw new SubmitAbort("Navê cureyê rêzimanî yê hilbijartî nediyar e."); } var loc = locateManeSection(pageContent, language, maneOrdinal); var lines = loc.lines; var m = /^(===[ ]*Mane)(\s+\d+)?([ ]*===)/.exec(lines[loc.maneLineIndex]); lines[loc.maneLineIndex] = "=== " + newSectionType + (m[2] ? m[2] : "") + " ==="; var nextLineIndex = loc.maneLineIndex + 1; if (nextLineIndex < lines.length && /^\{\{\s*cure\?\s*\|[^{}]*\}\}\s*$/.test(lines[nextLineIndex])) { lines.splice(nextLineIndex, 1); } return pageContent.slice(0, loc.langSectionIndex) + lines.join("\n"); } // ---- "guhartina pêşketî" (advanced editing): combine several independent per-sense edits into ONE save ---- // Threads pageContent through the same pure functions every single-field form already used // (updateSenseGloss/insertLeadingSenseTpl/insertSenseWords/insertPageSubsection), applying only the // pieces the caller actually filled in (see buildAdvancedPanel()'s own collectChanges()). A piece that // conflicts with something already on the page (maneid already set, a subsection that's already there) // is skipped with a warning rather than failing the whole save -- everything else the user changed still // goes through in the same edit. Throws SubmitAbort if literally nothing was filled in, so this can never // turn into a no-op save. function applyAdvancedChanges(pageContent, language, sectionType, sectionOrdinal, definitionLevel, changes) { var content = pageContent; var warnings = []; var appliedAnything = false; function tryApply(fn) { try { content = fn(); appliedAnything = true; } catch (e) { if (e instanceof SubmitAbort) { warnings.push(e.message); } else { throw e; } } } if (changes.gloss) { content = updateSenseGloss(content, language, sectionType, sectionOrdinal, definitionLevel, changes.gloss); appliedAnything = true; } if (changes.maneid) { tryApply(function () { return insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "maneid", [changes.maneid], { noExtend: true, noExtendLabel: "nasnavek (maneid)" }); }); } if (changes.etiket && changes.etiket.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "e", changes.etiket); appliedAnything = true; } if (changes.kategori && changes.kategori.length) { content = insertLeadingSenseTpl(content, language, sectionType, sectionOrdinal, definitionLevel, "K", changes.kategori); appliedAnything = true; } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { content = insertSenseWords(content, language, sectionType, sectionOrdinal, definitionLevel, group.key, words); appliedAnything = true; } }); if (changes.subsection) { tryApply(function () { return insertPageSubsection(content, language, sectionType, sectionOrdinal, changes.subsection.def, changes.subsection.content); }); } if (!appliedAnything) { throw new SubmitAbort("Tiştek nehat guhertin."); } return { content: content, warnings: warnings }; } // ---- per-definition UI: a small always-visible "+" toggle (no hover, so it works on mobile/touch too) ---- // Finds the button Gadget-wikt.add-examples.js already inserted for this definition, by its exact text. function findExampleButton($li) { var found = null; $li.find("a").each(function () { if ($(this).text().trim() === "Nimûneyeke bikaranînê lê zêde bike") { found = $(this); return false; } }); return found; } // Growing word list, ported from start.js's own makeModifierLi() + onSubInput(): every word is its own // always-visible row (word box + a "+" to attach one of the 10 WORD_MODIFIERS as a small pill above the // box + a "x" to drop the row); a fresh empty row appears automatically once the current last row gets // text, so the field never needs an explicit "add another word" button. Unlike the old chip-input this // replaces, duplicate words are allowed (start.js's own field allows them too) and there is no separate // commit step -- every row's own box is always live. function buildWordListField(placeholder) { var $list = $("<ol class='dsb-wordlist'></ol>"); function modDef(key) { var found = null; WORD_MODIFIERS.forEach(function (wm) { if (wm.key === key) { found = wm; } }); return found; } function makeRow() { var mods = []; var $li = $("<li class='dsb-word-li'></li>"); var $modsRow = $("<div class='dsb-word-mods'></div>").hide(); var $wordInput = $("<input type='text' class='dsb-input dsb-word-input'>").attr("placeholder", placeholder); var $addMod = $("<button type='button' class='dsb-mod-btn' title='Taybetiyekê lê zêde bike'>&#8853;</button>").hide(); var $removeRow = $("<button type='button' class='dsb-word-remove' title='Vê kelîmeyê jê bibe'>&#215;</button>").hide(); var $picker = $("<div class='dsb-mod-picker'></div>").hide(); var $boxRow = $("<div class='dsb-word-box-row'></div>").append($wordInput, $addMod, $removeRow); function usedKeys() { var used = {}; mods.forEach(function (mo) { used[mo.key] = true; }); return used; } function renderMods() { $modsRow.empty(); mods.forEach(function (mo, idx) { var $chip = $("<span class='dsb-word-mod-chip' role='button' tabindex='0'></span>").text(modChipLabel(mo)); var $x = $("<button type='button' class='dsb-word-mod-chip-remove' title='Vê taybetiyê jê bibe'>&#215;</button>"); $x.on("click", function (e) { e.stopPropagation(); mods.splice(idx, 1); renderMods(); }); $chip.on("click", function () { var def = modDef(mo.key); if (def) { openValueEditor(def, idx); } }); $chip.append($x); $modsRow.append($chip); }); $modsRow.toggle(!!mods.length); } // Same value-entry UI for both "add" (existingIdx === -1) and "edit" (click on an existing pill). function openValueEditor(mod, existingIdx) { $picker.hide(); var $wrap = $("<span class='dsb-mod-val-wrap'></span>"); var $valInput = $("<input type='text' class='dsb-input dsb-mod-val-input'>") .attr("placeholder", mod.hint + "…") .val(existingIdx === -1 ? "" : mods[existingIdx].value); var $confirm = $("<button type='button' class='dsb-mod-confirm' title='Erê'>&#10003;</button>"); var $cancel = $("<button type='button' class='dsb-mod-cancel' title='Betal'>&#10005;</button>"); function apply() { var v = $.trim($valInput.val()); if (v) { if (existingIdx === -1) { mods.push({ key: mod.key, value: v }); } else { mods[existingIdx].value = v; } renderMods(); } $wrap.remove(); $wordInput.trigger("focus"); } $confirm.on("click", apply); $cancel.on("click", function () { $wrap.remove(); $wordInput.trigger("focus"); }); $valInput.on("keydown", function (e) { if (e.which === 13) { e.preventDefault(); apply(); } else if (e.which === 27) { $wrap.remove(); $wordInput.trigger("focus"); } }); $wrap.append($valInput, $confirm, $cancel); $li.append($wrap); $valInput.trigger("focus"); } // The 10 pills are built lazily on first "+" open, not for every word row up front. var pillsBuilt = false; function buildPills() { if (pillsBuilt) { return; } pillsBuilt = true; WORD_MODIFIERS.forEach(function (mod) { var $pill = $("<button type='button' class='dsb-mod-pill'></button>").text(mod.label).attr("title", mod.hint); $pill.data("mod-key", mod.key); $pill.on("click", function (e) { e.preventDefault(); if ($pill.prop("disabled")) { return; } openValueEditor(mod, -1); }); $picker.append($pill); }); } $addMod.on("click", function (e) { e.preventDefault(); $list.find(".dsb-mod-picker").not($picker).hide(); buildPills(); var used = usedKeys(); $picker.find(".dsb-mod-pill").each(function () { var isUsed = !!used[$(this).data("mod-key")]; $(this).prop("disabled", isUsed).toggleClass("dsb-mod-pill-used", isUsed); }); $picker.toggle(); }); $removeRow.on("click", function () { $li.remove(); }); function updateButtons() { var hasWord = !!$.trim($wordInput.val()); $addMod.toggle(hasWord); $removeRow.toggle(hasWord); if (!hasWord) { $picker.hide(); } } updateButtons(); // Grows the list: typing into what is currently the last row appends a fresh empty one after it // (ported from start.js's onSubInput) -- so there is always exactly one empty trailing row to type // into, and the field never needs its own explicit "add word" button. $wordInput.on("input", function () { updateButtons(); var isLast = $li.is($list.children("li").last()); if (isLast && $.trim($wordInput.val()) !== "") { $list.append(makeRow()); } }); $wordInput.on("keydown", function (e) { if (e.which === 13) { // Enter moves on instead of inserting a newline e.preventDefault(); $wordInput.trigger("blur"); } }); $li.on("focusout", function () { setTimeout(function () { if (!$.contains($li.get(0), document.activeElement)) { $picker.hide(); } }, 150); }); $li.data("wordInput", $wordInput); $li.data("getRaw", function () { return joinWordValue($.trim($wordInput.val()), mods); }); $li.append($modsRow, $boxRow, $picker); return $li; } $list.append(makeRow()); return { $element: $list, values: function () { var vals = []; $list.children("li").each(function () { var raw = $(this).data("getRaw")(); if (raw) { vals.push(raw); } }); return vals; }, focus: function () { $list.children("li").first().data("wordInput").trigger("focus"); } }; } // Plain removable-tag field, start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip) -- // used for Etîket and Kategorî, which (unlike Hevmane/Dijmane/etc.) are simple value lists with no // per-word modifiers. Enter or "," commits the current text as a tag; Backspace on an empty input // removes the last tag; values() also commits whatever is still typed but not yet confirmed. function buildTagField(placeholder) { var $input = $("<input type='text' class='dsb-input dsb-tag-input'>").attr("placeholder", placeholder); var $element = $("<span class='dsb-tagfield'></span>").append($input); function currentValues() { var vals = []; $element.children(".dsb-tag").each(function () { vals.push($(this).data("value")); }); return vals; } function addTag(val) { val = $.trim(val || ""); if (!val || currentValues().indexOf(val) !== -1) { return; } var $tag = $("<span class='dsb-tag'></span>").text(val).data("value", val); var $remove = $("<button type='button' class='dsb-tag-remove' title='Jê bibe'>&#215;</button>"); $remove.on("click", function () { $tag.remove(); $input.trigger("focus"); }); $tag.append($remove); $tag.insertBefore($input); } $input.on("keydown", function (e) { if (e.which === 13 || e.which === 188) { // Enter or comma e.preventDefault(); addTag($input.val()); $input.val(""); } else if (e.which === 8 && !$input.val()) { $element.children(".dsb-tag").last().remove(); } }); $input.on("blur", function () { addTag($input.val()); $input.val(""); }); return { $element: $element, values: function () { addTag($input.val()); $input.val(""); return currentValues(); }, focus: function () { $input.trigger("focus"); } }; } // Builds the whole "guhartina pêşketî" panel into $quickRow: gloss (+ Oto-lînk bike) and the two // most-used word lists (Hevmane/Dijmane) sit directly in the picker row; the remaining SENSE_GROUPS word // lists, maneid, etîket, kategorî, and this POS block's own "+ beşek" subsection picker -- plus Nimûne/ // jêgirtin -- live behind a single "Zêdetir" dropdown -- plus one shared "Lê zêde bike" that queues // everything the user actually filled in as a single edit, via applyAdvancedChanges() and the shared // queueChange() helper (see this file's own floating queue box, built by ensureQueueBox()). Nimûne/ // jêgirtin is still an immediate proxy-click (see findExampleButton()), not a field this combined save // applies -- it opens a DIFFERENT gadget's own form with its own independent save -- it just sits in the // dropdown rather than as its own separate top-level link. function buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel) { var $nimune = $("<a href='#' class='dsb-quick-link'></a>").text("Nimûne/jêgirtin lê zêde bike"); $nimune.on("click", function (e) { e.preventDefault(); var $btn = findExampleButton($li); if ($btn) { $btn.trigger("click"); } else { mw.notify("Bişkoja amûra add-examples li vê maneyê nehat dîtin."); } $moreMenu.hide(); }); // getters holds one function per currently-OPEN box (key -> () => value); collectChanges() below only // ever reads from a box the user actually clicked to add -- there is no "always all 11 fields present" // state any more (that was tried and reverted -- see this file's own history notes). var getters = {}; // -- gloss ("Maneyê biguhêre" -- the one box that EDITS the sense's own wording; everything else here // only ever ADDS to the definition line) -- function addGlossField() { var $textarea = $("<textarea class='dsb-input dsb-edit-gloss' rows='2'></textarea>").attr("placeholder", "tê barkirin…").prop("disabled", true); var $autoLink = $("<button type='button' class='dsb-autolink'>Oto-lînk bike</button>").prop("disabled", true); var $status = $("<span class='dsb-status'></span>"); var originalGloss = null; fetchCurrentGloss(language, sectionType, sectionOrdinal, definitionLevel).then( function (gloss) { originalGloss = gloss; $textarea.val(gloss).prop("disabled", false); $autoLink.prop("disabled", false); }, function (codeOrAbort, result) { var message = codeOrAbort instanceof SubmitAbort ? codeOrAbort.message : "Nekarî maneya heyî bar bike: " + apiErrorMessage(codeOrAbort, result); $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text(message); } ); $autoLink.on("click", function () { var current = $textarea.val(); if (!$.trim(current)) { return; } $autoLink.prop("disabled", true); $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(current, function (linked) { $textarea.val(linked); $autoLink.prop("disabled", false); $status.text(""); }); }); getters.gloss = function () { var v = $.trim($textarea.val()); return (v && v !== originalGloss) ? v : null; }; return $("<div class='dsb-adv-group'></div>").append( $("<div class='dsb-adv-label'></div>").text("Mane"), $textarea, $("<div class='dsb-form-actions'></div>").append($autoLink, $status) ); } // -- one SENSE_GROUPS word-list box (Hevmane/Dijmane/etc.) -- function addWordField(group) { var field = buildWordListField(group.label + "…"); getters["word:" + group.key] = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text(group.label), field.$element); } // -- maneid (single value; re-adding one that already exists is rejected -- see applyAdvancedChanges) -- function addManeidField() { var $input = $("<input type='text' class='dsb-input' placeholder='nasnav…'>"); getters.maneid = function () { return $.trim($input.val()); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Nasnav (maneid)"), $input); } // -- etîket / kategorî -- function addEtiketField() { var field = buildTagField("Etîket…"); getters.etiket = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Etîket"), field.$element); } function addKategoriField() { var field = buildTagField("Kategorî…"); getters.kategori = function () { return field.values(); }; return $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Kategorî"), field.$element); } // -- this POS block's own "====" subsections (same picker buildSubsectionPanel() uses, folded in here) -- function addSubsectionField() { var existingHeaders = existingSubsectionHeadersInDom($h3); var availableSubsections = PAGE_SUBSECTIONS.filter(function (s) { return existingHeaders.indexOf(s.header) === -1; }); var $wrap = $("<div class='dsb-adv-group'></div>").append($("<div class='dsb-adv-label'></div>").text("Beşek (====)")); if (!availableSubsections.length) { $wrap.append($("<div class='dsb-status'></div>").text("Hemû beş jixwe li vê hene.")); return $wrap; } var $select = $("<select class='dsb-subsection-select'></select>"); availableSubsections.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var subWordField = null; function currentSubsection() { var id = $select.val(); return availableSubsections.filter(function (s) { return s.id === id; })[0]; } function renderSubField() { var s = currentSubsection(); $fieldWrap.empty(); subWordField = null; if (s.kind === "wordlist") { subWordField = buildWordListField(s.header + "…"); $fieldWrap.append(subWordField.$element); } else { $fieldWrap.append($("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>").attr("placeholder", s.header + "…")); } } $select.on("change", renderSubField); renderSubField(); getters.subsection = function () { var s = currentSubsection(); var content = s.kind === "wordlist" ? subWordField.values() : $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); var hasContent = s.kind === "wordlist" ? content.length > 0 : content !== ""; return hasContent ? { def: s, content: content } : null; }; $wrap.append($select, $fieldWrap); return $wrap; } // -- the picker row: gloss + the two most-used word groups (Hevmane/Dijmane, same SENSE_GROUPS.primary // flag start.js itself uses to feature them) sit directly in the row; everything else (the remaining // word groups, maneid, etîket, kategorî, subsection) lives behind a single "Zêdetir" dropdown -- back to // the pre-round-12 layout the user actually wanted, on top of round 12's click-to-open-a-box mechanic: // clicking any link (primary or from the dropdown) builds and appends its box to $openBoxes and hides // that link; the box's own "×" removes it, clears its getter, and un-hides the link -- several boxes can // be open at once, unlike the old "only one form open at a time" behavior (round 3-10's $below). ---- var FIELD_DEFS = [{ key: "gloss", label: "Maneyê biguhêre", build: addGlossField, primary: true }] .concat(SENSE_GROUPS.map(function (group) { return { key: "word:" + group.key, label: group.label, build: function () { return addWordField(group); }, primary: !!group.primary }; })) .concat([ { key: "maneid", label: "Nasnav (maneid)", build: addManeidField, primary: false }, { key: "etiket", label: "Etîket", build: addEtiketField, primary: false }, { key: "kategori", label: "Kategorî", build: addKategoriField, primary: false }, { key: "subsection", label: "Beşek (====)", build: addSubsectionField, primary: false } ]); var $picker = $("<div class='dsb-field-picker'></div>"); var $moreMenu = $("<div class='dsb-more-menu'></div>").hide(); var $openBoxes = $("<div class='dsb-open-boxes'></div>"); // Nimûne/jêgirtin sits first in the dropdown, ahead of every field-pick link. $moreMenu.append($nimune); FIELD_DEFS.forEach(function (def) { var $link = $("<a href='#' class='dsb-quick-link dsb-field-pick'></a>").text(def.key === "gloss" ? def.label : "+ " + def.label); $link.on("click", function (e) { e.preventDefault(); var $box = def.build(); var $remove = $("<a href='#' class='dsb-box-remove' title='Rake'>×</a>"); $remove.on("click", function (e2) { e2.preventDefault(); delete getters[def.key]; $box.remove(); $link.show(); }); $box.prepend($remove); $openBoxes.append($box); $link.hide(); $moreMenu.hide(); }); (def.primary ? $picker : $moreMenu).append($link); }); var $moreToggle = $("<a href='#' class='dsb-quick-link dsb-more-toggle'>Zêdetir</a>"); $moreToggle.on("click", function (e) { e.preventDefault(); $moreMenu.toggle(); }); $picker.append($moreToggle); // Closes the dropdown on an outside click, same as round 3-10's own "More" menu -- scoped to this // panel's own $moreToggle/$moreMenu, so it never touches another sense's panel. $(document).on("click", function (e) { if (!$(e.target).closest($moreToggle).length && !$(e.target).closest($moreMenu).length) { $moreMenu.hide(); } }); // -- combined save: whatever boxes are open right now, queued together via the shared queueChange() // helper (see its own comment) -- the actual save happens later, when the user clicks "Guhertinan qeyd // bike" on this gadget's own floating queue box. ---- // Small "not saved yet" preview of everything this one queued change will do, appended right after // $quickRow (i.e. in the same spot the panel itself sits, right under the sense's gloss) -- plain text, // not a real render of {{hevmane}}/etc., but placed where the real content will actually end up once // the page is reloaded after a real save. function buildChangesPreview(changes) { var $prev = $("<div class='dsb-preview-inline'></div>"); $prev.append($("<span class='dsb-preview-badge'></span>").text("nû — hîn nehatiye qeydkirin")); var $list = $("<ul class='dsb-preview-list'></ul>"); function plain(w) { return w.replace(/<[^<>]*>/g, ""); } if (changes.gloss) { $list.append($("<li></li>").text("Mane: " + changes.gloss)); } SENSE_GROUPS.forEach(function (group) { var words = changes.words && changes.words[group.key]; if (words && words.length) { $list.append($("<li></li>").text(group.label + ": " + words.map(plain).join(", "))); } }); if (changes.maneid) { $list.append($("<li></li>").text("Nasnav: " + changes.maneid)); } if (changes.etiket && changes.etiket.length) { $list.append($("<li></li>").text("Etîket: " + changes.etiket.join(", "))); } if (changes.kategori && changes.kategori.length) { $list.append($("<li></li>").text("Kategorî: " + changes.kategori.join(", "))); } if (changes.subsection) { $list.append($("<li></li>").text("+" + changes.subsection.def.header)); } $prev.append($list); return $prev; } function collectChanges() { var words = {}; SENSE_GROUPS.forEach(function (group) { var getter = getters["word:" + group.key]; words[group.key] = getter ? getter() : []; }); return { gloss: getters.gloss ? getters.gloss() : null, maneid: getters.maneid ? getters.maneid() : "", etiket: getters.etiket ? getters.etiket() : [], kategori: getters.kategori ? getters.kategori() : [], words: words, subsection: getters.subsection ? getters.subsection() : null }; } var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $cancel = $("<button type='button' class='dsb-cancel'>Betal bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $cancel, $status); $cancel.on("click", function () { $quickRow.hide(); }); $save.on("click", function () { var changes = collectChanges(); function afterLinkify() { queueChange( "guhartina pêşketî (DefSideBoxes)", function (baseContent) { return applyAdvancedChanges(baseContent, language, sectionType, sectionOrdinal, definitionLevel, changes); }, $save, $status, function () { var $prev = buildChangesPreview(changes); $quickRow.after($prev); return function () { $prev.remove(); }; } ); } $save.prop("disabled", true); // Same zero-links-gets-auto-linkified rule as every earlier round's gloss save -- only when the // gloss is actually part of this save, and only ever applied automatically when the user hasn't // already added a manual link themselves. if (changes.gloss && !/\[\[.+?\]\]/.test(changes.gloss)) { $status.removeClass("dsb-status-ok dsb-status-error").text("Tê lînkkirin…"); linkifyText(changes.gloss, function (linked) { changes.gloss = $.trim(linked); afterLinkify(); }); } else { afterLinkify(); } }); $quickRow.empty().append($picker, $moreMenu, $openBoxes, $actions); } // Attaches the pencil toggle to one leaf definition <li> -- clicking it reveals the "guhartina pêşketî" // (advanced editing) panel built by buildAdvancedPanel() above: gloss/Hevmane/Dijmane sit as direct picker // links, everything else (the remaining SENSE_GROUPS word lists, maneid, etîket, kategorî, this POS // block's own subsections) behind a "Zêdetir" dropdown -- clicking any of them opens its own box, several // can be open at once, then one shared "Lê zêde bike" queues everything currently open together into this // gadget's own floating queue box (see queueChange()) -- the real save only happens when the user clicks // that box's own "Guhertinan qeyd bike". function attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3) { if ($li.children(".dsb-toolbar").length) { return; } var $toolbar = $("<span class='dsb-toolbar'></span>"); var $toggle = $("<a href='#' class='dsb-toggle' title='Guhartina pêşketî'>✎</a>"); // Revealed by $toggle -- an indented panel under the sense (like en.wiktionary's own // "+Add example sentence +Add quotation More" row under a definition), not always visible. Built // lazily on first open (see buildAdvancedPanel()'s own fetchCurrentGloss() call) rather than eagerly // for every sense on the page. var $quickRow = $("<div class='dsb-quick-row'></div>").hide(); $toggle.on("click", function (e) { e.preventDefault(); $(".dsb-quick-row").not($quickRow).hide(); $quickRow.toggle(); if ($quickRow.is(":visible") && !$quickRow.data("built")) { buildAdvancedPanel($quickRow, $li, $h3, language, sectionType, sectionOrdinal, definitionLevel); $quickRow.data("built", true); } }); $toolbar.append($toggle); $li.prepend($toolbar); // Land $quickRow right after the sense's own gloss text -- before any existing "Hevmane: ..." <dl>, // citation <ul>, or the Nimûne/jêgirtin proxy link's own <ul>, not appended after all of that. var $firstBlock = $li.children("dl, ul, ol").first(); if ($firstBlock.length) { $firstBlock.before($quickRow); } else { $li.append($quickRow); } } // ---- per-section UI: "+ Beşek lê zêde bike" after a POS block's own content ---- // Reads the header text of "====" subsections already rendered under this POS heading, straight from the DOM. function existingSubsectionHeadersInDom($h3) { var headers = []; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); headers.push($hh.text().trim()); } } return headers; } // Finds where a NEW "====" subsection preview belongs in the live DOM, using the same canonical order // subsectionRankForHeader()/PAGE_SUBSECTIONS already give insertPageSubsection() for the real wikitext -- // so the preview shows up exactly where the real content will land after a save + reload, not just tacked // onto the end of the POS block. Returns either {insertBefore: $el} (an existing subsection that outranks // this one) or {insertAfter: $el} (nothing does -- goes at the end of the block). function domSubsectionInsertAnchor($h3, header) { var myRank = subsectionRankForHeader(header); var $last = headingOuter($h3); for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, h2, h3")) { break; } if ($cursor.is(".mw-heading4, h4")) { var $hh = $cursor.is("h4") ? $cursor : $cursor.find("h4").first(); var otherRank = subsectionRankForHeader($hh.text().trim()); if (otherRank !== -1 && otherRank > myRank) { return { insertBefore: $cursor }; } } $last = $cursor; } return { insertAfter: $last }; } // A small "not saved yet" preview of a page-level "====" subsection: a heading + its word list (or text), // dropped into the live page at its own canonical position (domSubsectionInsertAnchor()) so it reads as // "this is what will actually be here" rather than a form-panel status line. Plain text, not a real render // of {{kol3|...}}/etc. Returns the inserted element so the caller can remove it again (queue cancel, or // after a real save, when the page needs a reload to show the real thing anyway). function buildSubsectionPreviewDom($h3, s, content) { var $wrap = $("<div class='dsb-preview-block'></div>"); // A styled <div>, not a real <h4> -- existingSubsectionHeadersInDom() (".mw-heading4, h4") must never // mistake this live-only preview for an actual subsection already on the page, or a second "+ Beşek lê // zêde bike" would wrongly treat it as already there and hide it from the picker. $wrap.append($("<div class='dsb-preview-heading' role='heading' aria-level='4'></div>").text(s.header)); $wrap.append($("<span class='dsb-preview-badge'></span>").text("nû — hîn nehatiye qeydkirin")); if (s.kind === "wordlist") { var $list = $("<ul class='dsb-preview-list'></ul>"); content.forEach(function (w) { $list.append($("<li></li>").text(w.replace(/<[^<>]*>/g, ""))); }); $wrap.append($list); } else { $wrap.append($("<p class='dsb-preview-text'></p>").text(content)); } var anchor = domSubsectionInsertAnchor($h3, s.header); if (anchor.insertBefore) { anchor.insertBefore.before($wrap); } else { anchor.insertAfter.after($wrap); } return $wrap; } // Builds the subsection picker + its word-list/text field, saved via insertPageSubsection(). function buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal) { var existing = existingSubsectionHeadersInDom($h3); var available = PAGE_SUBSECTIONS.filter(function (s) { return existing.indexOf(s.header) === -1; }); if (!available.length) { $panel.text("Hemû beş jixwe li vê hene."); return; } var $select = $("<select class='dsb-subsection-select'></select>"); available.forEach(function (s) { $select.append($("<option></option>").val(s.id).text(s.header)); }); var $fieldWrap = $("<div class='dsb-subsection-field'></div>"); var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); function currentSubsection() { var id = $select.val(); return available.filter(function (s) { return s.id === id; })[0]; } var wordField = null; // set by renderField() whenever the current subsection is a wordlist one function renderField() { var s = currentSubsection(); $fieldWrap.empty(); wordField = null; if (s.kind === "wordlist") { wordField = buildWordListField(s.header + "…"); $fieldWrap.append(wordField.$element); } else { $fieldWrap.append( $("<textarea class='dsb-input dsb-subsection-text' rows='3'></textarea>") .attr("placeholder", s.header + "…") ); } } $select.on("change", renderField); renderField(); $save.on("click", function () { var s = currentSubsection(); var content; if (s.kind === "wordlist") { content = wordField.values(); if (!content.length) { return; } } else { content = $.trim($fieldWrap.find(".dsb-subsection-text").val() || ""); if (!content) { return; } } $save.prop("disabled", true); queueChange( "+" + s.header + " (DefSideBoxes)", function (pageContent) { return { content: insertPageSubsection(pageContent, language, sectionType, sectionOrdinal, s, content), warnings: [] }; }, $save, $status, function () { var $preview = buildSubsectionPreviewDom($h3, s, content); return function () { $preview.remove(); }; } ); }); $panel.empty().append($select, $fieldWrap, $actions); } // Builds the "choose a part of speech" picker that replaces an unclassified "=== Mane ===" placeholder // heading, saved via convertManeToPos(). Lists every name from sectionNames -- same canonical POS list // locateSection() itself accepts. function buildConvertPosPanel($panel, $h3, language, maneOrdinal) { var $select = $("<select class='dsb-convert-pos-select'></select>"); $select.append($("<option value=''></option>").text("— cureyekî hilbijêre —")); Object.keys(sectionNames).forEach(function (name) { $select.append($("<option></option>").val(name).text(name)); }); var $save = $("<button type='button' class='dsb-save'>Lê zêde bike</button>"); var $status = $("<span class='dsb-status'></span>"); var $actions = $("<div class='dsb-form-actions'></div>").append($save, $status); $save.on("click", function () { var chosen = $select.val(); if (!chosen) { $status.removeClass("dsb-status-ok").addClass("dsb-status-error").text("Pêşî cureyekî rêzimanî hilbijêre."); return; } $save.prop("disabled", true); $status.removeClass("dsb-status-error").text(""); queueChange( "Cureyê rêzimanî hate diyarkirin: " + chosen + " (DefSideBoxes)", function (pageContent) { return { content: convertManeToPos(pageContent, language, maneOrdinal, chosen), warnings: [] }; }, $save, $status, function () { // Preview: a small pending note right under the heading itself (its own correct spot on the // page), rather than rewriting the real heading text -- an in-place rewrite would need to be // reverted on failure/cancel but KEPT on a real success, and a real save failing partway // through would otherwise leave a real heading showing a name that was never actually saved. var $note = $("<div class='dsb-preview-inline dsb-preview-heading-note'></div>") .text("→ " + chosen + " — nû, hîn nehatiye qeydkirin"); headingOuter($h3).after($note); return function () { $note.remove(); }; } ); }); $panel.empty().append($select, $actions); } // Attaches the "+ Beşek lê zêde bike" trigger right after a POS block's own last element. function attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal) { if ($h3.data("dsbAttached")) { return; } $h3.data("dsbAttached", true); var $anchor = $ol; for (var $cursor = $ol.next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } $anchor = $cursor; } var $trigger = $("<a href='#' class='dsb-add-subsection'>+ Beşek lê zêde bike</a>"); var $panel = $("<div class='dsb-subsection-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildSubsectionPanel($panel, $h3, language, sectionType, sectionOrdinal); $panel.data("built", true); } }); $anchor.after($panel); $anchor.after($trigger); } // Attaches the "choose a part of speech" trigger right under an unclassified "=== Mane ===" placeholder // heading (see convertManeToPos()'s own comment for what that heading means). function attachManeConvertTrigger($h3) { if ($h3.data("dsbManeAttached")) { return; } $h3.data("dsbManeAttached", true); // languageCodeForOl() is really just "nearest preceding .besazimani[id] before this element in // document order" -- nothing ol-specific about it, so it works unchanged for a heading too. var language = languageCodeForOl($h3); if (!language) { return; } var maneOrdinal = sectionOrdinalWithinLanguage($h3); var $trigger = $("<a href='#' class='dsb-convert-pos-trigger'>Cureyê rêzimanî hilbijêre</a>"); var $panel = $("<div class='dsb-convert-pos-panel'></div>").hide(); $trigger.on("click", function (e) { e.preventDefault(); $panel.toggle(); if ($panel.is(":visible") && !$panel.data("built")) { buildConvertPosPanel($panel, $h3, language, maneOrdinal); $panel.data("built", true); } }); headingOuter($h3).after($panel); headingOuter($h3).after($trigger); } // ---- driver ---- function init() { $("h3").each(function () { var $h3 = $(this); var sectionType = sectionTypeOf($h3); if (!sectionType) { if (/^Mane(\s+\d+)?$/.test($h3.text().trim())) { attachManeConvertTrigger($h3); } return; // not a recognized word-sense section (Bilêvkirin, Etîmolojî, Çavkanî, ...) } var sectionOrdinal = sectionOrdinalWithinLanguage($h3); var $ol = null; for (var $cursor = headingOuter($h3).next(); $cursor.length; $cursor = $cursor.next()) { if ($cursor.is("ol")) { $ol = $cursor; break; } if ($cursor.is(".mw-heading2, .mw-heading3, .mw-heading4, .mw-heading5, .mw-heading6, h2, h3, h4, h5, h6")) { break; } } if (!$ol) { return; } var language = languageCodeForOl($ol); if (!language) { return; } eachLeafDefinition($ol, function ($li) { var definitionLevel = []; var $definitionItem = $li; while ($definitionItem.prop("tagName") === "LI") { definitionLevel.splice(0, 0, $definitionItem.prevAll("li:not(.mw-empty-elt)").length); $definitionItem = $definitionItem.parent().parent(); } definitionLevel.splice(0, 0, sectionType + "|" + sectionOrdinal); attachToolbar($li, language, sectionType, sectionOrdinal, definitionLevel, $h3); }); attachSubsectionTrigger($h3, $ol, language, sectionType, sectionOrdinal); }); } $(init); // </nowiki> })(); gtacpgnamha7g4nv6xw2emlbk9cvfh1 Bikarhêner:Wikihez/Gadget-DefSideBoxes.css 2 1358876 6347250 2026-08-30T20:05:24Z Wikihez 7344 Rûpel bi "/* Gadget-DefSideBoxes.css */ /* Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. */ .dsb-toolbar { display: inline-block; position: relative; margin-right: 6px; font-size: 11px; vertical-align: baseline; } .dsb-toggle { display: inline-block; width: 14px; height: 14px; line-height: 12px; text-align: center; border: 1px solid var( --border-color-base, #a2a9b1 ); border-radius: 2px; color:..." hat çêkirin 6347250 css text/css /* Gadget-DefSideBoxes.css */ /* Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. */ .dsb-toolbar { display: inline-block; position: relative; margin-right: 6px; font-size: 11px; vertical-align: baseline; } .dsb-toggle { display: inline-block; width: 14px; height: 14px; line-height: 12px; text-align: center; border: 1px solid var( --border-color-base, #a2a9b1 ); border-radius: 2px; color: var( --color-subtle, #72777d ); text-decoration: none; cursor: pointer; } .dsb-toggle:hover { background: var( --background-color-interactive, #eaecf0 ); } .dsb-menu { position: absolute; z-index: 10; left: 0; top: 18px; margin: 0; padding: 4px 0; list-style: none; min-width: 180px; background: var( --background-color-base, #fff ); border: 1px solid var( --border-color-base, #a2a9b1 ); border-radius: 2px; box-shadow: 0 1px 4px rgba( 0, 0, 0, .2 ); } .dsb-menu li { margin: 0; } .dsb-menu a { display: block; padding: 4px 10px; white-space: nowrap; color: var( --color-base, #202122 ); text-decoration: none; cursor: pointer; } .dsb-menu a:hover { background: var( --background-color-interactive, #eaecf0 ); } .dsb-inline-form { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-left: 6px; font-size: 11px; } .dsb-input { font-size: 11px; padding: 1px 4px; } .dsb-save, .dsb-cancel { font-size: 11px; padding: 1px 6px; cursor: pointer; } .dsb-status { font-size: 11px; } .dsb-add-subsection { display: inline-block; margin: 4px 0; font-size: 12px; color: var( --color-subtle, #72777d ); text-decoration: none; cursor: pointer; } .dsb-add-subsection:hover { text-decoration: underline; } .dsb-subsection-panel { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; max-width: 480px; margin: 4px 0 10px; padding: 8px; background: var( --background-color-neutral, #f8f9fa ); border: 1px solid var( --border-color-base, #a2a9b1 ); border-radius: 2px; } .dsb-subsection-select { font-size: 12px; } .dsb-subsection-field { flex: 1 1 200px; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; font-size: 12px; } /* Minerva (mobile): narrower viewport, keep the dropdown/panel from overflowing offscreen. */ .skin-minerva .dsb-menu { min-width: 160px; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } ljn0jmgr87h6zj32qib8ot7hr17r9ti 6347261 6347250 2026-08-30T20:46:39Z Wikihez 7344 6347261 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; position: relative; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 26px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px; } .dsb-inline-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Pill/chip word field ──────────────────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified here to plain type-and-commit chips with no suggestion panel. */ .dsb-chipfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-chipfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-chip-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-chip-remove:hover { color: var(--dsb-danger); } .dsb-chipfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-chipfield .dsb-input:focus { box-shadow: none; } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select { box-sizing: border-box; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { flex: 1 1 200px; min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-field .dsb-chipfield { width: 100%; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-chipfield .dsb-input { min-height: 32px; } .dsb-chip-remove { padding: 0 6px; } .dsb-inline-form { display: flex; } .dsb-inline-form .dsb-chipfield, .dsb-inline-form .dsb-input { flex: 1 1 100%; min-width: 0; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } .dsb-subsection-panel { flex-direction: column; align-items: stretch; } .dsb-subsection-select { width: 100%; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } a0tmc112znz1s4pseqmpd5xb3ophe7h 6347263 6347261 2026-08-30T21:17:38Z Wikihez 7344 6347263 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; position: relative; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 26px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } lfxcqhlyci94jz35aicclr1u93tue4r 6347270 6347263 2026-08-30T21:42:50Z Wikihez 7344 6347270 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── Per-definition quick links + "More" ───────────────────────────── Mirrors en.wiktionary's own DefSideBoxes: a couple of always-visible text links (there, "+Add example sentence"/"+Add quotation"; here, Hevmane/Dijmane) plus a "More" link that opens everything else in a dropdown -- no square icon button, just text, so it reads as part of the definition line rather than a separate toolbar. */ .dsb-toolbar { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 10px; position: relative; margin-right: 8px; font-family: var(--dsb-sans); font-size: 12.5px; vertical-align: baseline; } .dsb-quick-link, .dsb-more-toggle { color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus, .dsb-more-toggle:hover, .dsb-more-toggle:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 20px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toolbar { font-size: 14px; gap: 12px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } d9eqg0ymaj1ytpf2nfs0nbefrenr5hv 6347272 6347270 2026-08-30T21:49:37Z Wikihez 7344 6347272 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Quick-links row + "More" ───────────────────────────────────────── Revealed by the "+" toggle above -- an indented row under the sense (like en.wiktionary's own "+Add example sentence +Add quotation More" row under a definition), not always visible and not squeezed onto the definition's own line. */ .dsb-quick-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 12.5px; } .dsb-quick-link, .dsb-more-toggle { color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus, .dsb-more-toggle:hover, .dsb-more-toggle:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. Anchored to .dsb-quick-row (its "More" link's own container), not .dsb-toolbar. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 20px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px 26px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; gap: 12px; margin-left: 20px; } .dsb-below { margin-left: 20px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } c3owybparmedjkjjhukwjcete1285qs 6347280 6347272 2026-08-30T22:43:10Z Wikihez 7344 6347280 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Quick-links row + "More" ───────────────────────────────────────── Revealed by the "+" toggle above -- an indented row under the sense (like en.wiktionary's own "+Add example sentence +Add quotation More" row under a definition), not always visible and not squeezed onto the definition's own line. */ .dsb-quick-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 12.5px; } .dsb-quick-link, .dsb-more-toggle { color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus, .dsb-more-toggle:hover, .dsb-more-toggle:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. Anchored to .dsb-quick-row (its "More" link's own container), not .dsb-toolbar. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 20px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px 26px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── "Maneyê biguhêre" (edit sense) ───────────────────────────────── Same shape as .dsb-subsection-text; kept as its own rule since it lives on a definition <li>, not inside the subsection panel. Bold marks it as the primary action, ahead of the plain "+ Hevmane" / "+ Dijmane" add-links next to it in the same row. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } .dsb-quick-link-edit { font-weight: 600; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; gap: 12px; margin-left: 20px; } .dsb-below { margin-left: 20px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } ly05qlfmabvlnvswodzgx9xlgp8dhd9 6347308 6347280 2026-08-31T00:38:51Z Wikihez 7344 6347308 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Quick-links row + "More" ───────────────────────────────────────── Revealed by the "+" toggle above -- an indented row under the sense (like en.wiktionary's own "+Add example sentence +Add quotation More" row under a definition), not always visible and not squeezed onto the definition's own line. */ .dsb-quick-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 12.5px; } .dsb-quick-link, .dsb-more-toggle { color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus, .dsb-more-toggle:hover, .dsb-more-toggle:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. Anchored to .dsb-quick-row (its "More" link's own container), not .dsb-toolbar. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 20px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px 26px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── "Maneyê biguhêre" (edit sense) ───────────────────────────────── Same shape as .dsb-subsection-text; kept as its own rule since it lives on a definition <li>, not inside the subsection panel. Bold marks it as the primary action, ahead of the plain "+ Hevmane" / "+ Dijmane" add-links next to it in the same row. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } .dsb-quick-link-edit { font-weight: 600; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; gap: 12px; margin-left: 20px; } .dsb-below { margin-left: 20px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } 8vc0w4ahuxpgpffp63e2u6sw9evdsh6 6347313 6347308 2026-08-31T00:53:48Z Wikihez 7344 6347313 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── Quick-links row + "More" ───────────────────────────────────────── Revealed by the "+" toggle above -- an indented row under the sense (like en.wiktionary's own "+Add example sentence +Add quotation More" row under a definition), not always visible and not squeezed onto the definition's own line. */ .dsb-quick-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 12.5px; } .dsb-quick-link, .dsb-more-toggle { color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus, .dsb-more-toggle:hover, .dsb-more-toggle:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Dropdown menu ─────────────────────────────────────────────────── Card surface, hairline border, no shadow — the form's .wiktku-addsection-menu pattern, whose rows are tinted on hover rather than greyed. Anchored to .dsb-quick-row (its "More" link's own container), not .dsb-toolbar. */ .dsb-menu { position: absolute; z-index: 60; left: 0; top: 20px; margin: 0; padding: 6px; list-style: none; min-width: 15em; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-menu li { margin: 0; list-style: none; } .dsb-menu a { display: block; padding: 8px 10px; border-radius: 7px; border-bottom: 0; white-space: nowrap; font-size: 13.5px; font-weight: 500; color: var(--dsb-ink); text-decoration: none; cursor: pointer; } .dsb-menu a:hover, .dsb-menu a:focus { background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); text-decoration: none; } /* ── Opened sense-group form ───────────────────────────────────────── Lives in its own row below the definition's existing content (see attachToolbar's $below in the .js), in the same spot the rendered "#: {{tpl|...}}" line will end up once saved -- not squeezed onto the definition's own line next to the toggle. */ .dsb-below { margin: 8px 0 4px 26px; } .dsb-inline-form { display: flex; flex-direction: column; align-items: stretch; gap: 8px; font-family: var(--dsb-sans); font-size: 13px; } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── "Maneyê biguhêre" (edit sense) ───────────────────────────────── Same shape as .dsb-subsection-text; kept as its own rule since it lives on a definition <li>, not inside the subsection panel. Bold marks it as the primary action, ahead of the plain "+ Hevmane" / "+ Dijmane" add-links next to it in the same row. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } .dsb-quick-link-edit { font-weight: 600; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the menu/panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-menu { min-width: 14em; max-width: 90vw; } .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; gap: 12px; margin-left: 20px; } .dsb-below { margin-left: 20px; } .dsb-menu a { padding: 11px 12px; white-space: normal; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } egpvvzeuy9no6tuqd7qvzz7m4kyltu9 6347318 6347313 2026-08-31T01:20:35Z Wikihez 7344 6347318 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, stacked in one sunken card (same shape as .dsb-subsection-panel) and saved together with one Qeyd bike, instead of each living in its own separate mini-form/separate edit. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* One field (its label + input) within the panel. */ .dsb-adv-group { margin-bottom: 14px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; padding: 12px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } fwym9l767xozobolf3alewm2t0dct8a 6347320 6347318 2026-08-31T06:37:51Z Wikihez 7344 6347320 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, stacked in one sunken card (same shape as .dsb-subsection-panel) and saved together with one Qeyd bike, instead of each living in its own separate mini-form/separate edit. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* The picker row: one "+ <field>" link per addable box, wrapping as needed -- clicking one opens its box below and hides the link itself (see .dsb-open-boxes); the box's own .dsb-box-remove un-hides it. */ .dsb-field-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 10px; } .dsb-field-picker .dsb-quick-link { margin-bottom: 0; } /* Boxes the user has actually opened, stacked in the order they were added -- several can be open at once. */ .dsb-open-boxes { display: flex; flex-direction: column; } /* One field (its label + input) within the panel -- always a currently-open, removable box. */ .dsb-adv-group { position: relative; margin-bottom: 14px; padding-right: 20px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-box-remove { position: absolute; top: 0; right: 0; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-box-remove:hover, .dsb-box-remove:focus { color: var(--dsb-accent-deep); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; padding: 12px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } 01sc7t8yk23srgh17zcfs4veroqu7rw 6347323 6347320 2026-08-31T09:40:26Z Wikihez 7344 6347323 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, stacked in one sunken card (same shape as .dsb-subsection-panel) and saved together with one Qeyd bike, instead of each living in its own separate mini-form/separate edit. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* The picker row: gloss + the two primary word groups (Hevmane/Dijmane) as direct "+ <field>" links, plus a "Zêdetir" toggle for the rest (see .dsb-more-menu) -- clicking any link opens its box below and hides the link itself (see .dsb-open-boxes); the box's own .dsb-box-remove un-hides it. */ .dsb-field-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 10px; } .dsb-field-picker .dsb-quick-link { margin-bottom: 0; } /* The "Zêdetir" dropdown: every non-primary field link, hidden until the toggle is clicked. */ .dsb-more-menu { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 8px 10px; margin: -4px 0 10px; background: var(--dsb-card-sunken); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-field); } .dsb-more-menu .dsb-quick-link { margin-bottom: 0; } /* Boxes the user has actually opened, stacked in the order they were added -- several can be open at once. */ .dsb-open-boxes { display: flex; flex-direction: column; } /* One field (its label + input) within the panel -- always a currently-open, removable box. */ .dsb-adv-group { position: relative; margin-bottom: 14px; padding-right: 20px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-box-remove { position: absolute; top: 0; right: 0; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-box-remove:hover, .dsb-box-remove:focus { color: var(--dsb-accent-deep); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; padding: 12px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } 0wsv9lq426unpms2b3s9vdkd7kkd0g5 6347326 6347323 2026-08-31T10:00:37Z Wikihez 7344 6347326 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, saved together with one Qeyd bike, instead of each living in its own separate mini-form/separate edit. A plain inline row, NOT a bordered/background card -- closer to en.wiktionary's own bare "+Add example sentence +Add quotation More" toolbar than to .dsb-subsection-panel's own sunken-card look. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* The picker row: gloss + the two primary word groups (Hevmane/Dijmane) as direct "+ <field>" links, plus a "Zêdetir" toggle for the rest (see .dsb-more-menu) -- clicking any link opens its box below and hides the link itself (see .dsb-open-boxes); the box's own .dsb-box-remove un-hides it. */ .dsb-field-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 10px; } .dsb-field-picker .dsb-quick-link { margin-bottom: 0; } /* The "Zêdetir" dropdown: every non-primary field link, hidden until the toggle is clicked. */ .dsb-more-menu { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 8px 10px; margin: -4px 0 10px; background: var(--dsb-card-sunken); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-field); } .dsb-more-menu .dsb-quick-link { margin-bottom: 0; } /* Boxes the user has actually opened, stacked in the order they were added -- several can be open at once. */ .dsb-open-boxes { display: flex; flex-direction: column; } /* One field (its label + input) within the panel -- always a currently-open, removable box. */ .dsb-adv-group { position: relative; margin-bottom: 14px; padding-right: 20px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-box-remove { position: absolute; top: 0; right: 0; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-box-remove:hover, .dsb-box-remove:focus { color: var(--dsb-accent-deep); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink { min-height: 40px; padding: 8px 16px; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save { color: #14213a; } } crxf0ai4yy0xkpwkmsew18hh47vqrrb 6347332 6347326 2026-08-31T10:22:44Z Wikihez 7344 6347332 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, queued together with one "Lê zêde bike", instead of each living in its own separate mini-form/separate edit. A plain inline row, NOT a bordered/background card -- closer to en.wiktionary's own bare "+Add example sentence +Add quotation More" toolbar than to .dsb-subsection-panel's own sunken-card look. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* The picker row: gloss + the two primary word groups (Hevmane/Dijmane) as direct "+ <field>" links, plus a "Zêdetir" toggle for the rest (see .dsb-more-menu) -- clicking any link opens its box below and hides the link itself (see .dsb-open-boxes); the box's own .dsb-box-remove un-hides it. */ .dsb-field-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 10px; } .dsb-field-picker .dsb-quick-link { margin-bottom: 0; } /* The "Zêdetir" dropdown: every non-primary field link, hidden until the toggle is clicked. */ .dsb-more-menu { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 8px 10px; margin: -4px 0 10px; background: var(--dsb-card-sunken); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-field); } .dsb-more-menu .dsb-quick-link { margin-bottom: 0; } /* Boxes the user has actually opened, stacked in the order they were added -- several can be open at once. */ .dsb-open-boxes { display: flex; flex-direction: column; } /* One field (its label + input) within the panel -- always a currently-open, removable box. */ .dsb-adv-group { position: relative; margin-bottom: 14px; padding-right: 20px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-box-remove { position: absolute; top: 0; right: 0; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-box-remove:hover, .dsb-box-remove:focus { color: var(--dsb-accent-deep); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Live "not saved yet" previews ───────────────────────────────────── Dropped into the actual rendered page, at the change's own correct spot (see buildSubsectionPreviewDom()/buildChangesPreview() in the .js), instead of only a status line inside the panel that queued it. Dashed edge + a small badge mark it as pending, not real content -- it disappears again on "Betal bike" or once the real save lands. */ .dsb-preview-block, .dsb-preview-inline { margin: 8px 0; padding: 8px 12px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-accent-tint); border: 1px dashed var(--dsb-accent-edge); border-radius: var(--dsb-r-field); } .dsb-preview-inline { margin-left: 26px; max-width: 520px; } .dsb-preview-heading { margin: 0 0 4px; font-size: 15px; font-weight: 600; color: var(--dsb-ink); } .dsb-preview-badge { display: inline-block; margin-bottom: 6px; padding: 1px 8px; font-size: 11px; font-weight: 500; color: var(--dsb-accent-deep); background: var(--dsb-card); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); } .dsb-preview-badge-inline { margin-left: 8px; margin-bottom: 0; vertical-align: middle; } .dsb-preview-list, .dsb-preview-text { margin: 0; padding-left: 18px; } .dsb-preview-text { padding-left: 0; } /* ── Floating save-queue widget ───────────────────────────────────── This gadget's own version of the small floating box the real Gadget-Editor - kuwikt.js singleton shows -- built and owned by this file instead of piggybacking on that (unrelated) gadget, so its copy only ever talks about DefSideBoxes' own queued changes. One "Lê zêde bike" click anywhere on the page adds a line here; "Guhertinan qeyd bike" makes the one real save; "Betal bike" drops everything queued (and every live preview) without touching the page. */ .dsb-queue-box { position: fixed; top: 60px; right: 16px; z-index: 1000; box-sizing: border-box; width: 280px; max-width: calc(100vw - 32px); max-height: calc(100vh - 90px); overflow-y: auto; padding: 12px 14px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card); border: 1px solid var(--dsb-accent); border-radius: var(--dsb-r-card); box-shadow: 0 4px 18px rgba(0, 0, 0, 0.16); } .dsb-queue-title { margin-right: 20px; font-size: 13px; font-weight: 600; color: var(--dsb-ink); } .dsb-queue-close { float: right; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-queue-close:hover, .dsb-queue-close:focus { color: var(--dsb-accent-deep); } .dsb-queue-list { margin: 8px 0; padding-left: 18px; max-height: 160px; overflow-y: auto; } .dsb-queue-list li { margin-bottom: 4px; } .dsb-queue-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; } .dsb-queue-save, .dsb-queue-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } .dsb-queue-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-queue-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-queue-save:disabled { opacity: 0.55; cursor: progress; } .dsb-queue-cancel { background: transparent; border: 1px solid var(--dsb-field-edge); color: var(--dsb-ink-3); } .dsb-queue-cancel:hover { border-color: var(--dsb-ink-3); color: var(--dsb-ink); } .dsb-queue-status { margin-top: 6px; font-size: 12.5px; color: var(--dsb-muted); } .dsb-queue-status.dsb-status-ok { color: var(--dsb-ok); } .dsb-queue-status.dsb-status-error { color: var(--dsb-danger); } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink, .dsb-queue-save, .dsb-queue-cancel { min-height: 40px; padding: 8px 16px; } .dsb-queue-box { top: auto; bottom: 8px; right: 8px; left: 8px; width: auto; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save, html.skin-theme-clientpref-night .dsb-queue-save, html.skin-nightmode .dsb-queue-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save, html.skin-theme-clientpref-os .dsb-queue-save { color: #14213a; } } cq72h5le5bsh7pp4sorzc06k6yyn7da 6347336 6347332 2026-08-31T11:07:27Z Wikihez 7344 6347336 css text/css /* Gadget-DefSideBoxes.css Skin-agnostic (vector, vector2022, minerva) -- no :hover-only reveal, no absolute positioning against the page. Visual layer matched to MediaWiki:Gadget-wiktku-start/styles.css ("SÊWIRANA NÛ"): same cream surfaces, warm ink, single blue accent, 10/12px radii, pill buttons. Those tokens are declared on #wiktku-start-form, which does not exist on an article page -- so the same values are re-declared here under a --dsb-* prefix (a page-scope --wikt-* block would leak the palette onto unrelated gadgets). */ :root { --dsb-card: #fffdf8; --dsb-card-sunken: #fbf8f1; --dsb-rule: #ded6c8; --dsb-rule-soft: #efe8db; --dsb-card-edge: #e6dfd2; --dsb-field-edge: #cfc7b8; --dsb-field-bg: #fff; --dsb-ink: #1c1a17; --dsb-ink-2: #3d3830; --dsb-ink-3: #57514a; --dsb-muted: #8a8378; --dsb-placeholder: #b3ab9e; --dsb-accent: #2a5db0; --dsb-accent-deep: #22406f; --dsb-accent-tint: #eef2fa; --dsb-accent-edge: #d5def0; --dsb-ok: #3d8a55; --dsb-danger: #9c3a28; --dsb-r-field: 10px; --dsb-r-card: 12px; --dsb-r-pill: 999px; --dsb-sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --dsb-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; } /* ── The "+" toggle on a definition ────────────────────────────────── Same shape as the form's .wiktku-mod-btn: soft-cornered square, accent tint, accent glyph. Sized to the definition line's own text, so it never pushes the line's leading around. */ .dsb-toolbar { display: inline-block; margin-right: 8px; font-family: var(--dsb-sans); vertical-align: baseline; } .dsb-toggle { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 1px solid var(--dsb-accent-edge); border-radius: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent); font-size: 13px; line-height: 1; text-decoration: none; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease; } .dsb-toggle:hover, .dsb-toggle:focus { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); background: var(--dsb-accent-tint); text-decoration: none; } /* ── "Guhartina pêşketî" (advanced editing) panel ────────────────────── Revealed by the pencil toggle above -- every action this gadget offers for one sense (gloss, word-list groups, maneid/etîket/kategorî), plus this POS block's own subsections, queued together with one "Lê zêde bike", instead of each living in its own separate mini-form/separate edit. A plain inline row, NOT a bordered/background card -- closer to en.wiktionary's own bare "+Add example sentence +Add quotation More" toolbar than to .dsb-subsection-panel's own sunken-card look. */ .dsb-quick-row { display: flex; flex-direction: column; align-items: stretch; gap: 4px; box-sizing: border-box; max-width: 520px; margin: 4px 0 4px 26px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); } .dsb-quick-link { align-self: flex-start; margin-bottom: 10px; color: var(--dsb-accent); text-decoration: none; white-space: nowrap; cursor: pointer; } .dsb-quick-link:hover, .dsb-quick-link:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* The picker row: gloss + the two primary word groups (Hevmane/Dijmane) as direct "+ <field>" links, plus a "Zêdetir" toggle for the rest (see .dsb-more-menu) -- clicking any link opens its box below and hides the link itself (see .dsb-open-boxes); the box's own .dsb-box-remove un-hides it. */ .dsb-field-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 10px; } .dsb-field-picker .dsb-quick-link { margin-bottom: 0; } /* The "Zêdetir" dropdown: every non-primary field link (plus Nimûne/jêgirtin, which sits first) stacked as a plain vertical list, hidden until the toggle is clicked -- a real dropdown menu, not a bordered/background panel -- same flattened, no-card treatment .dsb-quick-row itself got in round 14. */ .dsb-more-menu { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 2px 0 10px 4px; } .dsb-more-menu .dsb-quick-link { margin-bottom: 0; } /* Boxes the user has actually opened, stacked in the order they were added -- several can be open at once. */ .dsb-open-boxes { display: flex; flex-direction: column; } /* One field (its label + input) within the panel -- always a currently-open, removable box. */ .dsb-adv-group { position: relative; margin-bottom: 14px; padding-right: 20px; } .dsb-adv-label { margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--dsb-ink-3); } .dsb-box-remove { position: absolute; top: 0; right: 0; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-box-remove:hover, .dsb-box-remove:focus { color: var(--dsb-accent-deep); } .dsb-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .dsb-input { box-sizing: border-box; min-width: 16em; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-input::placeholder { color: var(--dsb-placeholder); opacity: 1; } .dsb-input:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } /* ── Plain tag field (Etîket, Kategorî) ──────────────────────────────── start.js's own buildChipField() pattern (its .wiktku-dfn-chipfield-chip), simplified to plain type-and-commit tags with no suggestion panel -- unlike Hevmane/Dijmane/etc., these two values carry no modifiers. */ .dsb-tagfield { box-sizing: border-box; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 16em; padding: 4px 6px; background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); transition: border-color 0.12s ease, box-shadow 0.12s ease; } .dsb-tagfield:focus-within { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); } .dsb-tag { display: inline-flex; align-items: center; gap: 6px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; padding: 3px 6px 3px 10px; } .dsb-tag-remove { border: 0; background: transparent; color: var(--dsb-muted); font-size: 13px; line-height: 1; cursor: pointer; padding: 0 2px; } .dsb-tag-remove:hover { color: var(--dsb-danger); } .dsb-tagfield .dsb-input { flex: 1 1 8em; min-width: 8em; border: 0; padding: 3px 2px; background: transparent; box-shadow: none; } .dsb-tagfield .dsb-input:focus { box-shadow: none; } /* ── Word list with modifier pills ─────────────────────────────────── start.js's own makeModifierLi() pattern (Hevmane/Dijmane/Formên alternatîv/Termên koordîne/Jornav/Jêrnav): every word is its own always-visible row -- a word box plus a "+" that attaches one of the 10 WORD_MODIFIERS as a small pill shown above the box. A fresh empty row is appended automatically once the current last one gets text. */ .dsb-wordlist { margin: 0; padding-left: 0; list-style: none; } .dsb-word-li { margin-bottom: 6px; } .dsb-word-li:last-child { margin-bottom: 0; } .dsb-word-mods { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px; } .dsb-word-mod-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 11.5px; padding: 3px 4px 3px 10px; cursor: pointer; } .dsb-word-mod-chip-remove { border: 0; background: transparent; color: var(--dsb-accent-deep); font-size: 12px; line-height: 1; cursor: pointer; padding: 0 2px; opacity: 0.7; } .dsb-word-mod-chip-remove:hover { color: var(--dsb-danger); opacity: 1; } .dsb-word-box-row { display: flex; align-items: center; gap: 6px; } .dsb-word-box-row .dsb-word-input { flex: 1 1 auto; min-width: 0; } .dsb-mod-btn, .dsb-word-remove { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; cursor: pointer; transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease; } .dsb-mod-btn { border: 1px solid var(--dsb-accent-edge); background: var(--dsb-accent-tint); color: var(--dsb-accent); } .dsb-mod-btn:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-word-remove { border: 1px solid var(--dsb-field-edge); background: var(--dsb-field-bg); color: var(--dsb-muted); } .dsb-word-remove:hover { border-color: var(--dsb-danger); color: var(--dsb-danger); } .dsb-mod-picker { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; margin-top: 6px; padding: 8px; background: var(--dsb-card); border: 1px solid var(--dsb-rule); border-radius: var(--dsb-r-card); box-shadow: none; } .dsb-mod-pill { font-family: var(--dsb-sans); background: var(--dsb-accent-tint); color: var(--dsb-accent-deep); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); font-size: 12px; white-space: nowrap; padding: 5px 10px; cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease; } .dsb-mod-pill:hover { border-color: var(--dsb-accent); background: var(--dsb-accent); color: #fff; } .dsb-mod-pill:disabled, .dsb-mod-pill.dsb-mod-pill-used { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); cursor: not-allowed; opacity: 0.7; } .dsb-mod-pill:disabled:hover, .dsb-mod-pill.dsb-mod-pill-used:hover { background: var(--dsb-card-sunken); border-color: var(--dsb-rule); color: var(--dsb-muted); } .dsb-mod-val-wrap { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 6px; } .dsb-mod-val-input { flex: 1 1 auto; min-width: 0; max-width: 16em; } .dsb-mod-confirm, .dsb-mod-cancel { flex: 0 0 auto; box-sizing: border-box; width: 26px; height: 26px; padding: 0; line-height: 1; font-size: 13px; border-radius: 7px; background: var(--dsb-accent-tint); cursor: pointer; } .dsb-mod-confirm { border: 1px solid var(--dsb-ok); color: var(--dsb-ok); } .dsb-mod-cancel { border: 1px solid var(--dsb-danger); color: var(--dsb-danger); } .dsb-save, .dsb-cancel, .dsb-autolink { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } /* One filled pill per row — the same rule the form's footer follows. */ .dsb-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-save:disabled { opacity: 0.55; cursor: progress; } .dsb-cancel { background: transparent; border: 1px solid transparent; color: var(--dsb-ink-3); } .dsb-cancel:hover { border-color: var(--dsb-field-edge); color: var(--dsb-ink); } /* An outline pill, distinct from both the filled .dsb-save and the plain-text .dsb-cancel -- a secondary utility action, not the primary save nor a dismissal. */ .dsb-autolink { background: transparent; border: 1px solid var(--dsb-accent-edge); color: var(--dsb-accent); } .dsb-autolink:hover { border-color: var(--dsb-accent); color: var(--dsb-accent-deep); } .dsb-autolink:disabled { opacity: 0.55; cursor: progress; } /* Status line. Color comes from .dsb-status-ok/.dsb-status-error (added by the .js on success/failure) rather than an inline style, so these tokens (and dark mode) apply. */ .dsb-status { font-family: var(--dsb-sans); font-size: 12.5px; color: var(--dsb-muted); } .dsb-status-ok { color: var(--dsb-ok); } .dsb-status-error { color: var(--dsb-danger); } /* ── "+ Beşek lê zêde bike" ────────────────────────────────────────── An accent-coloured action link, like the form's .wiktku-adv-toggle: it opens something, so it is not muted grey. */ .dsb-add-subsection, .dsb-convert-pos-trigger { display: inline-flex; align-items: center; gap: 6px; margin: 8px 0; font-family: var(--dsb-sans); font-size: 14px; font-weight: 500; color: var(--dsb-accent); text-decoration: none; border-bottom: 0; cursor: pointer; } .dsb-add-subsection:hover, .dsb-add-subsection:focus, .dsb-convert-pos-trigger:hover, .dsb-convert-pos-trigger:focus { color: var(--dsb-accent-deep); text-decoration: underline; } /* ── Subsection panel ──────────────────────────────────────────────── A sunken card rather than a grey utility box; fields stack so the picker and its input are not competing for one narrow row. */ .dsb-subsection-panel, .dsb-convert-pos-panel { display: flex; flex-direction: column; align-items: stretch; gap: 10px; box-sizing: border-box; max-width: 520px; margin: 6px 0 14px; padding: 14px 16px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card-sunken); border: 1px solid var(--dsb-card-edge); border-radius: var(--dsb-r-card); } .dsb-subsection-select, .dsb-convert-pos-select { box-sizing: border-box; width: 100%; max-width: 100%; padding: 6px 10px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink); background: var(--dsb-field-bg); border: 1px solid var(--dsb-field-edge); border-radius: var(--dsb-r-field); } .dsb-subsection-select:focus, .dsb-convert-pos-select:focus { border-color: var(--dsb-accent); box-shadow: 0 0 0 3px var(--dsb-accent-tint); outline: 0; } .dsb-subsection-field { min-width: 0; } .dsb-subsection-words, .dsb-subsection-text { box-sizing: border-box; width: 100%; min-width: 0; } .dsb-subsection-text { line-height: 1.6; resize: vertical; } /* ── Gloss field inside the advanced-editing panel ──────────────────── Same shape as .dsb-subsection-text. */ .dsb-edit-gloss { width: 100%; line-height: 1.6; resize: vertical; } /* ── Live "not saved yet" previews ───────────────────────────────────── Dropped into the actual rendered page, at the change's own correct spot (see buildSubsectionPreviewDom()/buildChangesPreview() in the .js), instead of only a status line inside the panel that queued it. Dashed edge + a small badge mark it as pending, not real content -- it disappears again on "Betal bike" or once the real save lands. */ .dsb-preview-block, .dsb-preview-inline { margin: 8px 0; padding: 8px 12px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-accent-tint); border: 1px dashed var(--dsb-accent-edge); border-radius: var(--dsb-r-field); } .dsb-preview-inline { margin-left: 26px; max-width: 520px; } .dsb-preview-heading { margin: 0 0 4px; font-size: 15px; font-weight: 600; color: var(--dsb-ink); } .dsb-preview-badge { display: inline-block; margin-bottom: 6px; padding: 1px 8px; font-size: 11px; font-weight: 500; color: var(--dsb-accent-deep); background: var(--dsb-card); border: 1px solid var(--dsb-accent-edge); border-radius: var(--dsb-r-pill); } .dsb-preview-badge-inline { margin-left: 8px; margin-bottom: 0; vertical-align: middle; } .dsb-preview-list, .dsb-preview-text { margin: 0; padding-left: 18px; } .dsb-preview-text { padding-left: 0; } /* ── Floating save-queue widget ───────────────────────────────────── This gadget's own version of the small floating box the real Gadget-Editor - kuwikt.js singleton shows -- built and owned by this file instead of piggybacking on that (unrelated) gadget, so its copy only ever talks about DefSideBoxes' own queued changes. One "Lê zêde bike" click anywhere on the page adds a line here; "Guhertinan qeyd bike" makes the one real save; "Betal bike" drops everything queued (and every live preview) without touching the page. */ .dsb-queue-box { position: fixed; top: 60px; right: 16px; z-index: 1000; box-sizing: border-box; width: 280px; max-width: calc(100vw - 32px); max-height: calc(100vh - 90px); overflow-y: auto; padding: 12px 14px; font-family: var(--dsb-sans); font-size: 13px; color: var(--dsb-ink-2); background: var(--dsb-card); border: 1px solid var(--dsb-accent); border-radius: var(--dsb-r-card); box-shadow: 0 4px 18px rgba(0, 0, 0, 0.16); } .dsb-queue-title { margin-right: 20px; font-size: 13px; font-weight: 600; color: var(--dsb-ink); } .dsb-queue-close { float: right; color: var(--dsb-ink-3); text-decoration: none; font-size: 14px; line-height: 1; cursor: pointer; } .dsb-queue-close:hover, .dsb-queue-close:focus { color: var(--dsb-accent-deep); } .dsb-queue-list { margin: 8px 0; padding-left: 18px; max-height: 160px; overflow-y: auto; } .dsb-queue-list li { margin-bottom: 4px; } .dsb-queue-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; } .dsb-queue-save, .dsb-queue-cancel { font-family: var(--dsb-sans); font-size: 13px; font-weight: 500; padding: 6px 14px; border-radius: var(--dsb-r-pill); cursor: pointer; transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; } .dsb-queue-save { background: var(--dsb-accent); border: 1px solid var(--dsb-accent); color: #fff; } .dsb-queue-save:hover { background: var(--dsb-accent-deep); border-color: var(--dsb-accent-deep); } .dsb-queue-save:disabled { opacity: 0.55; cursor: progress; } .dsb-queue-cancel { background: transparent; border: 1px solid var(--dsb-field-edge); color: var(--dsb-ink-3); } .dsb-queue-cancel:hover { border-color: var(--dsb-ink-3); color: var(--dsb-ink); } .dsb-queue-status { margin-top: 6px; font-size: 12.5px; color: var(--dsb-muted); } .dsb-queue-status.dsb-status-ok { color: var(--dsb-ok); } .dsb-queue-status.dsb-status-error { color: var(--dsb-danger); } /* ── Minerva (mobile) ──────────────────────────────────────────────── Narrower viewport: keep the panel on screen and give every tap target the form's 44px minimum. */ .skin-minerva .dsb-quick-row, .skin-minerva .dsb-subsection-panel, .skin-minerva .dsb-convert-pos-panel { max-width: 100%; } @media (max-width: 720px), (pointer: coarse) { .dsb-toggle { width: 28px; height: 28px; font-size: 15px; } .dsb-quick-row { font-size: 14px; margin-left: 20px; } .dsb-input, .dsb-subsection-select, .dsb-convert-pos-select { min-height: 40px; /* >=16px stops iOS Safari zooming the page on focus. */ font-size: 16px; } .dsb-mod-btn, .dsb-word-remove, .dsb-mod-confirm, .dsb-mod-cancel { width: 36px; height: 36px; font-size: 15px; } .dsb-mod-pill { padding: 8px 12px; } .dsb-mod-val-input { max-width: none; } .dsb-tagfield .dsb-input { min-height: 32px; } .dsb-tag-remove { padding: 0 6px; } .dsb-save, .dsb-cancel, .dsb-autolink, .dsb-queue-save, .dsb-queue-cancel { min-height: 40px; padding: 8px 16px; } .dsb-queue-box { top: auto; bottom: 8px; right: 8px; left: 8px; width: auto; } } /* ── Dark mode ─────────────────────────────────────────────────────── Same warm dark palette and same explicit-signal-only rule as the form's stylesheet: no bare prefers-color-scheme fallback, since legacy Vector sets no theme class and would go dark on its own. */ html.skin-theme-clientpref-night, html.skin-nightmode { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-night .dsb-save, html.skin-nightmode .dsb-save, html.skin-theme-clientpref-night .dsb-queue-save, html.skin-nightmode .dsb-queue-save { color: #14213a; } @media screen and (prefers-color-scheme: dark) { html.skin-theme-clientpref-os { --dsb-card: #201e1a; --dsb-card-sunken: #1a1916; --dsb-card-edge: #322e28; --dsb-rule: #3a3630; --dsb-rule-soft: #2c2924; --dsb-field-edge: #4a453d; --dsb-field-bg: #191815; --dsb-ink: #ece7dd; --dsb-ink-2: #d5cfc4; --dsb-ink-3: #b3aca1; --dsb-muted: #8f887c; --dsb-placeholder: #6d675e; --dsb-accent: #7ba7e8; --dsb-accent-deep: #cfe0f8; --dsb-accent-tint: #1c2839; --dsb-accent-edge: #35496b; --dsb-ok: #7cc094; --dsb-danger: #e5907c; } html.skin-theme-clientpref-os .dsb-save, html.skin-theme-clientpref-os .dsb-queue-save { color: #14213a; } } m153yuy3rhv8ap398wn7nn8a2mutgwk Wîkîferheng:Rêveber/Wikihez 4 1358877 6347266 2026-08-30T21:34:05Z Wikihez 7344 Rûpel bi "== {{subst:SUBPAGENAME}} == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din jî çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir a..." hat çêkirin 6347266 wikitext text/x-wiki == Wikihez == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din jî çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir aciz bikim loma dixwazim li vir bibim Interface admîn. Hûn dikarin şirove û dengên xwe li jêr binivîsin.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:34, 30 tebax 2026 (UTC) === Dengdan === {{dengdan|destpêk=31.08.2026|dawî=07.09.2026}} <!-- piştî dengdan dest pê kir vê şablonê {{dengdan|destpêk=|dawî=}}, û kengî xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bo ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo dengê erênî. --> ==== Dij ==== <!-- Li jêr '# {{na}} ~~~~' binivîse ji bo dengê neyînî. --> ==== Bêalî ==== <!-- Li jêr '# {{bêalî}} ~~~~' binivîse ji bo dengê bêalî. --> === Gotûbêj === <!-- Fikrên xwe bi şablona {{şirove}} li jêr binivîse. --> [[Kategorî:Dengdan|Wikihez]] 1v2sdle2lb54xa6l95d6blkj2islew8 6347267 6347266 2026-08-30T21:34:25Z Wikihez 7344 /* Wikihez */ (bi [[MediaWiki:Gadget-AjaxEdit.js|AjaxEdit]]ê re) 6347267 wikitext text/x-wiki == Wikihez == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din ên JS/CSSê çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir aciz bikim loma dixwazim li vir bibim Interface admîn. Hûn dikarin şirove û dengên xwe li jêr binivîsin.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:34, 30 tebax 2026 (UTC) === Dengdan === {{dengdan|destpêk=31.08.2026|dawî=07.09.2026}} <!-- piştî dengdan dest pê kir vê şablonê {{dengdan|destpêk=|dawî=}}, û kengî xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bo ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo dengê erênî. --> ==== Dij ==== <!-- Li jêr '# {{na}} ~~~~' binivîse ji bo dengê neyînî. --> ==== Bêalî ==== <!-- Li jêr '# {{bêalî}} ~~~~' binivîse ji bo dengê bêalî. --> === Gotûbêj === <!-- Fikrên xwe bi şablona {{şirove}} li jêr binivîse. --> [[Kategorî:Dengdan|Wikihez]] 49p1uv4dsa5vmuz8ghv7622s0uvc4kn 6347291 6347267 2026-08-30T23:30:21Z Bikarhêner 3719 /* Wikihez */ 6347291 wikitext text/x-wiki == Wikihez == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din ên JS/CSSê çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir aciz bikim loma dixwazim li vir bibim Interface admîn. Hûn dikarin şirove û dengên xwe li jêr binivîsin.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:34, 30 tebax 2026 (UTC) === Dengdan === {{dengdan|destpêk=31.08.2026|dawî=07.09.2026}} <!-- piştî dengdan dest pê kir vê şablonê {{dengdan|destpêk=|dawî=}}, û kengî xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bo ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo dengê erênî. --> # {{erê}} Ji karên teknîkî baş fam dike. Lewma hewce ye ku bibe admîn. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 23:30, 30 tebax 2026 (UTC) ==== Dij ==== <!-- Li jêr '# {{na}} ~~~~' binivîse ji bo dengê neyînî. --> ==== Bêalî ==== <!-- Li jêr '# {{bêalî}} ~~~~' binivîse ji bo dengê bêalî. --> === Gotûbêj === <!-- Fikrên xwe bi şablona {{şirove}} li jêr binivîse. --> [[Kategorî:Dengdan|Wikihez]] slmdk3cjhj4el4qqnakgxtrgdto06ph 6347340 6347291 2026-08-31T11:49:06Z Ghybu 1393 /* Dij */ 6347340 wikitext text/x-wiki == Wikihez == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din ên JS/CSSê çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir aciz bikim loma dixwazim li vir bibim Interface admîn. Hûn dikarin şirove û dengên xwe li jêr binivîsin.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:34, 30 tebax 2026 (UTC) === Dengdan === {{dengdan|destpêk=31.08.2026|dawî=07.09.2026}} <!-- piştî dengdan dest pê kir vê şablonê {{dengdan|destpêk=|dawî=}}, û kengî xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bo ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo dengê erênî. --> # {{erê}} Ji karên teknîkî baş fam dike. Lewma hewce ye ku bibe admîn. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 23:30, 30 tebax 2026 (UTC) ==== Dij ==== <!-- Li jêr '# {{na}} ~~~~' binivîse ji bo dengê neyînî. --> * {{na}} Mixabin, nikare xwe kontrol bike, bnr. [https://ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:tarih%C3%A7i&oldid=6240164], [https://ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:helbest&oldid=6236598#Advocacy], [https://ku.wikipedia.org/w/index.php?title=W%C3%AEk%C3%AEpediya:R%C3%AAveber/Balyozxane&diff=prev&oldid=1131978]. Rêveberên ku li vira ne jî tiştekî nawên. Bi vî awayî, mafên wekî vitira di destên wî de, di demên bê de dikarin biproblem bin. ==== Bêalî ==== <!-- Li jêr '# {{bêalî}} ~~~~' binivîse ji bo dengê bêalî. --> === Gotûbêj === <!-- Fikrên xwe bi şablona {{şirove}} li jêr binivîse. --> [[Kategorî:Dengdan|Wikihez]] o2zge5rstbxw9cxs1ubucpdpzyfgnik 6347341 6347340 2026-08-31T11:49:28Z Ghybu 1393 /* Dij */ îmze 6347341 wikitext text/x-wiki == Wikihez == Merheba, Ez, {{b|Wikihez}}, dixwazim amûrên din ên JS/CSSê çêkim daku guhartina rûpelan hêsantir be, amûrên heyî nû bikim yan baştir bikim. Ji bo ku rûpelên JS û CSSê bi hêsanî biguherînim ji min re heqên [[:meta:Interface administrators|Interface Admin]] lazim e. Mala wî ava hevalê {{b|Bikarhêner}} gelek alîkariya min kir di vî warî de lê xwestina alîkariyê her daîm ne tiştekî xweş e û naxwazim wî zêdetir aciz bikim loma dixwazim li vir bibim Interface admîn. Hûn dikarin şirove û dengên xwe li jêr binivîsin.[[Bikarhêner:Wikihez|Wikihez]] ([[Gotûbêja bikarhêner:Wikihez|gotûbêj]]) 21:34, 30 tebax 2026 (UTC) === Dengdan === {{dengdan|destpêk=31.08.2026|dawî=07.09.2026}} <!-- piştî dengdan dest pê kir vê şablonê {{dengdan|destpêk=|dawî=}}, û kengî xilas bû vê şablonê {{dengdan/borî|destpêk=|dawî=}} bi kar bînin. --> ==== Bo ==== <!-- Li jêr '# {{erê}} ~~~~' binivîse ji bo dengê erênî. --> # {{erê}} Ji karên teknîkî baş fam dike. Lewma hewce ye ku bibe admîn. -- [[Bikarhêner:Bikarhêner|Bikarhêner]] ([[Gotûbêja bikarhêner:Bikarhêner|gotûbêj]]) 23:30, 30 tebax 2026 (UTC) ==== Dij ==== <!-- Li jêr '# {{na}} ~~~~' binivîse ji bo dengê neyînî. --> * {{na}} Mixabin, nikare xwe kontrol bike, bnr. [https://ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:tarih%C3%A7i&oldid=6240164], [https://ku.wiktionary.org/w/index.php?title=Got%C3%BBb%C3%AAj:helbest&oldid=6236598#Advocacy], [https://ku.wikipedia.org/w/index.php?title=W%C3%AEk%C3%AEpediya:R%C3%AAveber/Balyozxane&diff=prev&oldid=1131978]. Rêveberên ku li vira ne jî tiştekî nawên. Bi vî awayî, mafên wekî vitira di destên wî de, di demên bê de dikarin biproblem bin. --[[Bikarhêner:Ghybu|Ghybu]] ([[Gotûbêja bikarhêner:Ghybu|gotûbêj]]) 11:49, 31 tebax 2026 (UTC) ==== Bêalî ==== <!-- Li jêr '# {{bêalî}} ~~~~' binivîse ji bo dengê bêalî. --> === Gotûbêj === <!-- Fikrên xwe bi şablona {{şirove}} li jêr binivîse. --> [[Kategorî:Dengdan|Wikihez]] bb13qvi1pvkg05oaf5pez4wlbe8vy2q