# MediaWiki:Gadget-twinkleprotect-2020.js

From faraghaib
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.

    // <nowiki>

    (function($) {

    /*
     ****************************************
     *** twinkleprotect.js: Protect/RPP module
     ****************************************
     * Mode of invocation:     Tab ("PP"/"RPP")
     * Active on:              Non-special, non-MediaWiki pages
     */

    // Note: a lot of code in this module is re-used/called by batchprotect.

    Twinkle.protect = function twinkleprotect() {
    	if (mw.config.get('wgNamespaceNumber') < 0 || mw.config.get('wgNamespaceNumber') === 8) {
    		return;
    	}

    	Twinkle.addPortletLink(Twinkle.protect.callback, Morebits.userIsSysop ? 'حفاظت' : 'حفاظت', 'tw-rpp', // localized
    		Morebits.userIsSysop ? 'حفاظت صفحه' : 'درخواست حفاظت صفحه'); // localized
    };

    Twinkle.protect.callback = function twinkleprotectCallback() {
    	var Window = new Morebits.simpleWindow(620, 530);
    	Window.setTitle(Morebits.userIsSysop ? 'اعمال، درخواست یا برچسب‌گذاری حفاظت صفحه' : 'درخواست یا برچسب‌گذاری حفاظت صفحه'); // localized
    	Window.setScriptName('توینکل'); // localized
    	Window.addFooterLink('الگوهای حفاظت', 'الگو:الگوهای حفاظت'); // localized
    	Window.addFooterLink('سیاست حفاظت', 'وپ:حفاظت'); // localized
    	Window.addFooterLink('راهنمای توینکل', 'وپ:تل/توضیحات#حفاظت'); // localized

    	var form = new Morebits.quickForm(Twinkle.protect.callback.evaluate);
    	var actionfield = form.append({
    		type: 'field',
    		label: 'نوع کنش' // localized
    	});
    	if (Morebits.userIsSysop) {
    		actionfield.append({
    			type: 'radio',
    			name: 'actiontype',
    			event: Twinkle.protect.callback.changeAction,
    			list: [
    				{
    					label: 'محافظت صفحه', // localized
    					value: 'protect',
    					tooltip: 'اجرای حفاظت بر روی صفحه.', // localized
    					checked: true
    				}
    			]
    		});
    	}
    	actionfield.append({
    		type: 'radio',
    		name: 'actiontype',
    		event: Twinkle.protect.callback.changeAction,
    		list: [
    			{
    				label: 'درخواست حفاظت صفحه', // localized
    				value: 'request',
    				tooltip: 'اگر می خواهید ' + (Morebits.userIsSysop ? ' بجای اینکه خودتان شخصا محافظت را اجرا کنید،' : 'از طریق وپ:دمص درخواست دهید'), // localized
    				checked: !Morebits.userIsSysop
    			},
    			{
    				label: 'برچسب‌زدن صفحه با الگوی حفاظت', // localized
    				value: 'tag',
    				tooltip: 'اگر مدیر حفاظت‌کننده فراموش کرده باشد برچسب بزند یا خودتان بدون افزودن برچسب حفاظت را اجرا کرده‌اید، از اینجا می‌توانید برچسب را اعمال کنید', // localized
    				disabled: mw.config.get('wgArticleId') === 0 || mw.config.get('wgPageContentModel') === 'Scribunto'
    			}
    		]
    	});

    	form.append({ type: 'field', label: 'پیش‌فرض', name: 'field_preset' });
    	form.append({ type: 'field', label: '1', name: 'field1' });
    	form.append({ type: 'field', label: '2', name: 'field2' });

    	form.append({ type: 'submit' });

    	var result = form.render();
    	Window.setContent(result);
    	Window.display();

    	// We must init the controls
    	var evt = document.createEvent('Event');
    	evt.initEvent('change', true, true);
    	result.actiontype[0].dispatchEvent(evt);

    	// get current protection level asynchronously
    	Twinkle.protect.fetchProtectionLevel();
    };

    // Contains the current protection level in an object
    // Once filled, it will look something like:
    // { edit: { level: "sysop", expiry: <some date>, cascade: true }, ... }
    Twinkle.protect.currentProtectionLevels = {};

    // returns a jQuery Deferred object, usage:
    //   Twinkle.protect.fetchProtectingAdmin(apiObject, pageName, protect/stable).done(function(admin_username) { ...code... });
    Twinkle.protect.fetchProtectingAdmin = function twinkleprotectFetchProtectingAdmin(api, pageName, protType, logIds) {
    	logIds = logIds || [];

    	return api.get({
    		format: 'json',
    		action: 'query',
    		list: 'logevents',
    		letitle: pageName,
    		letype: protType
    	}).then(function(data) {
    		// don't check log entries that have already been checked (e.g. don't go into an infinite loop!)
    		var event = data.query ? $.grep(data.query.logevents, function(le) {
    			return $.inArray(le.logid, logIds);
    		})[0] : null;
    		if (!event) {
    			// fail gracefully
    			return null;
    		} else if (event.action === 'move_prot' || event.action === 'move_stable') {
    			return twinkleprotectFetchProtectingAdmin(api, protType === 'protect' ? event.params.oldtitle_title : event.params.oldtitle, protType, logIds.concat(event.logid));
    		}
    		return event.user;
    	});
    };

    // mw.loader.getState('ext.flaggedRevs.review') returns null if the
    // FlaggedRevs extension is not registered.  Previously, this was done with
    // wgFlaggedRevsParams, but after 1.34-wmf4 it is no longer exported if empty
    // (https://gerrit.wikimedia.org/r/c/mediawiki/extensions/FlaggedRevs/+/508427)
    Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLevel() {

    	var api = new mw.Api();
    	var protectDeferred = api.get({
    		format: 'json',
    		indexpageids: true,
    		action: 'query',
    		list: 'logevents',
    		letype: 'protect',
    		letitle: mw.config.get('wgPageName'),
    		prop: mw.loader.getState('ext.flaggedRevs.review') ? 'info|flagged' : 'info',
    		inprop: 'protection',
    		titles: mw.config.get('wgPageName')
    	});
    	var stableDeferred = api.get({
    		format: 'json',
    		action: 'query',
    		list: 'logevents',
    		letype: 'stable',
    		letitle: mw.config.get('wgPageName')
    	});

    	var earlyDecision = [protectDeferred];
    	if (mw.loader.getState('ext.flaggedRevs.review')) {
    		earlyDecision.push(stableDeferred);
    	}

    	$.when.apply($, earlyDecision).done(function(protectData, stableData) {
    		// $.when.apply is supposed to take an unknown number of promises
    		// via an array, which it does, but the type of data returned varies.
    		// If there are two or more deferreds, it returns an array (of objects),
    		// but if there's just one deferred, it retuns a simple object.
    		// This is annoying.
    		protectData = $(protectData).toArray();

    		var pageid = protectData[0].query.pageids[0];
    		var page = protectData[0].query.pages[pageid];
    		var current = {}, adminEditDeferred;

    		$.each(page.protection, function(index, protection) {
    			if (protection.type !== 'aft') {
    				current[protection.type] = {
    					level: protection.level,
    					expiry: protection.expiry,
    					cascade: protection.cascade === ''
    				};
    				// logs report last admin who made changes to either edit/move/create protection, regardless if they only modified one of them
    				if (!adminEditDeferred) {
    					adminEditDeferred = Twinkle.protect.fetchProtectingAdmin(api, mw.config.get('wgPageName'), 'protect');
    				}
    			}
    		});

    		if (page.flagged) {
    			current.stabilize = {
    				level: page.flagged.protection_level,
    				expiry: page.flagged.protection_expiry
    			};
    			adminEditDeferred = Twinkle.protect.fetchProtectingAdmin(api, mw.config.get('wgPageName'), 'stable');
    		}

    		// show the protection level and log info
    		Twinkle.protect.hasProtectLog = !!protectData[0].query.logevents.length;
    		Twinkle.protect.hasStableLog = mw.loader.getState('ext.flaggedRevs.review') ? !!stableData[0].query.logevents.length : false;
    		Twinkle.protect.currentProtectionLevels = current;

    		if (adminEditDeferred) {
    			adminEditDeferred.done(function(admin) {
    				if (admin) {
    					$.each(['edit', 'move', 'create', 'stabilize'], function(i, type) {
    						if (Twinkle.protect.currentProtectionLevels[type]) {
    							Twinkle.protect.currentProtectionLevels[type].admin = admin;
    						}
    					});
    				}
    				Twinkle.protect.callback.showLogAndCurrentProtectInfo();
    			});
    		} else {
    			Twinkle.protect.callback.showLogAndCurrentProtectInfo();
    		}
    	});
    };

    Twinkle.protect.callback.showLogAndCurrentProtectInfo = function twinkleprotectCallbackShowLogAndCurrentProtectInfo() {
    	var currentlyProtected = !$.isEmptyObject(Twinkle.protect.currentProtectionLevels);

    	if (Twinkle.protect.hasProtectLog || Twinkle.protect.hasStableLog) {
    		var $linkMarkup = $('<span>');

    		if (Twinkle.protect.hasProtectLog) {
    			$linkMarkup.append(
    				$('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: mw.config.get('wgPageName'), type: 'protect'}) + '">سیاههٔ محافظت</a>'), // localized
    				Twinkle.protect.hasStableLog ? $('<span> &bull; </span>') : null
    			);
    		}

    		if (Twinkle.protect.hasStableLog) {
    			$linkMarkup.append($('<a target="_blank" href="' + mw.util.getUrl('Special:Log', {action: 'view', page: mw.config.get('wgPageName'), type: 'stable'}) + '">سیاههٔ تغییرات در انتظار</a>)')); // localized
    		}

    		Morebits.status.init($('div[name="hasprotectlog"] span')[0]);
    		Morebits.status.warn(
    			currentlyProtected ? 'محافظت‌های پیشین' : 'این صفحه در گذشته مورد حفاظت قرار گرفته‌است', // localized
    			$linkMarkup[0]
    		);
    	}

    	Morebits.status.init($('div[name="currentprot"] span')[0]);
    	var protectionNode = [], statusLevel = 'info';

    	if (currentlyProtected) {
    		$.each(Twinkle.protect.currentProtectionLevels, function(type, settings) {
    			var label = type === 'stabilize' ? 'تغییرات در حال انتظار' : Morebits.string.toUpperCaseFirstChar(type); // localized
    			protectionNode.push($('<b>' + label + ': ' + settings.level + '</b>')[0]);
    			if (settings.expiry === 'infinity') {
    				protectionNode.push(' (بی‌پایان) '); // localized
    			} else {
    				protectionNode.push(' (زمان سرآمدن ' + new Date(settings.expiry).toUTCString() + ') '); // localized
    			}
    			if (settings.cascade) {
    				protectionNode.push('(آبشاری) '); // localized
    			}
    			if (settings.admin) {
    				var adminLink = '<a target="_blank" href="' + mw.util.getUrl('User talk:' + settings.admin) + '">' + settings.admin + '</a>';
    				protectionNode.push($('<span>توسط ' + adminLink + '&nbsp;</span>')[0]); // localized
    			}
    			protectionNode.push($('<span> \u2022 </span>')[0]);
    		});
    		protectionNode = protectionNode.slice(0, -1); // remove the trailing bullet
    		statusLevel = 'warn';
    	} else {
    		protectionNode.push($('<b>محافظت نشده</b>')[0]); // localized
    	}

    	Morebits.status[statusLevel]('سطح محافظت فعلی', protectionNode); // localized
    };

    Twinkle.protect.callback.changeAction = function twinkleprotectCallbackChangeAction(e) {
    	var field_preset;
    	var field1;
    	var field2;
    	var isTemplate = mw.config.get('wgNamespaceNumber') === 10 || mw.config.get('wgNamespaceNumber') === 828;

    	switch (e.target.values) {
    		case 'protect':
    			field_preset = new Morebits.quickForm.element({ type: 'field', label: 'پیش‌تنظیم', name: 'field_preset' });
    			field_preset.append({
    				type: 'select',
    				name: 'category',
    				label: 'انتخاب یک پیش‌فرض:', // localized
    				event: Twinkle.protect.callback.changePreset,
    				list: mw.config.get('wgArticleId') ?
    					Twinkle.protect.protectionTypes.filter(function(v) {
    						return isTemplate || v.label !== 'حفاظت الگو';
    					}) :
    					Twinkle.protect.protectionTypesCreate
    			});

    			field2 = new Morebits.quickForm.element({ type: 'field', label: 'گزینه‌های حفاظت', name: 'field2' }); // localized
    			field2.append({ type: 'div', name: 'currentprot', label: ' ' });  // holds the current protection level, as filled out by the async callback
    			field2.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
    			// for existing pages
    			if (mw.config.get('wgArticleId')) {
    				field2.append({
    					type: 'checkbox',
    					name: 'editmodify',
    					event: Twinkle.protect.formevents.editmodify,
    					list: [
    						{
    							label: 'تغییر حفاظت در برابر ویرایش', // localized
    							value: 'editmodify',
    							tooltip: 'درصورت خاموش‌کردن این جعبه، سطح حفاظت از ویرایش و زمان سرآمدن به همان شکلی که هستند باقی می‌مانند', // localized
    							checked: true
    						}
    					]
    				});
    				var editlevel = field2.append({
    					type: 'select',
    					name: 'editlevel',
    					label: 'محافظت در برابر ویرایش:', // localized
    					event: Twinkle.protect.formevents.editlevel
    				});
    				editlevel.append({
    					type: 'option',
    					label: 'همه', // localized
    					value: 'all'
    				});
    				editlevel.append({
    					type: 'option',
    					label: 'تأییدشدهٔ خودکار', // localized
    					value: 'autoconfirmed'
    				});
    				editlevel.append({
    					type: 'option',
    					label: 'تأییدشدهٔ پایدار', // localized
    					value: 'extendedconfirmed'
    				});
    				if (isTemplate) {
    					editlevel.append({
    						type: 'option',
    						label: 'ویرایشگر الگو', // localized
    						value: 'templateeditor'
    					});
    				}
    				editlevel.append({
    					type: 'option',
    					label: 'مدیر', // localized
    					value: 'sysop',
    					selected: true
    				});
    				field2.append({
    					type: 'select',
    					name: 'editexpiry',
    					label: 'سرآمدن:', // localized
    					event: function(e) {
    						if (e.target.value === 'custom') {
    							Twinkle.protect.doCustomExpiry(e.target);
    						}
    					},
    					// default expiry selection is conditionally set in Twinkle.protect.callback.changePreset
    					list: [
    						{ label: '۱ ساعت', value: '1 hour' }, // localized
    						{ label: '۲ ساعت', value: '2 hours' }, // localized
    						{ label: '۳ ساعت', value: '3 hours' }, // localized
    						{ label: '۶ ساعت', value: '6 hours' }, // localized
    						{ label: '۱۲ ساعت', value: '12 hours' }, // localized
    						{ label: '۱ روز', value: '1 day' }, // localized
    						{ label: '۲ روز', value: '2 days' }, // localized
    						{ label: '۳ روز', value: '3 days' }, // localized
    						{ label: '۴ روز', value: '4 days' }, // localized
    						{ label: '۱ هفته', value: '1 week' }, // localized
    						{ label: '۲ هفته', value: '2 weeks' }, // localized
    						{ label: '۱ ماه', value: '1 month' }, // localized
    						{ label: '۲ ماه', value: '2 months' }, // localized
    						{ label: '۳ ماه', value: '3 months' }, // localized
    						{ label: '۱ سال', value: '1 year' }, // localized
    						{ label: 'بی‌پایان', value: 'indefinite' }, // localized
    						{ label: 'دلخواه', value: 'custom' } // localized
    					]
    				});
    				field2.append({
    					type: 'checkbox',
    					name: 'movemodify',
    					event: Twinkle.protect.formevents.movemodify,
    					list: [
    						{
    							label: 'تغییر حفاظت از انتقال', // localized
    							value: 'movemodify',
    							tooltip: 'اگر این جعبه خاموش باشد، سطح حفاظت از انتقال و زمان سرآمدن به همان شکلی که هستند باقی‌می‌مانند', // localized
    							checked: true
    						}
    					]
    				});
    				var movelevel = field2.append({
    					type: 'select',
    					name: 'movelevel',
    					label: 'حفاظت دربرابر انتقال:', // localized
    					event: Twinkle.protect.formevents.movelevel
    				});
    				movelevel.append({
    					type: 'option',
    					label: 'همه', // localized
    					value: 'all'
    				});
    				movelevel.append({
    					type: 'option',
    					label: 'تأیید‌شدهٔ پایدار', // localized
    					value: 'extendedconfirmed'
    				});
    				if (isTemplate) {
    					movelevel.append({
    						type: 'option',
    						label: 'ویرایشگر الگو', // localized
    						value: 'templateeditor'
    					});
    				}
    				movelevel.append({
    					type: 'option',
    					label: 'مدیر', // localized
    					value: 'sysop',
    					selected: true
    				});
    				field2.append({
    					type: 'select',
    					name: 'moveexpiry',
    					label: 'سرآمدن:', // localized
    					event: function(e) {
    						if (e.target.value === 'custom') {
    							Twinkle.protect.doCustomExpiry(e.target);
    						}
    					},
    					// default expiry selection is conditionally set in Twinkle.protect.callback.changePreset
    					list: [
    						{ label: '۱ ساعت', value: '1 hour' }, // localized
    						{ label: '۲ ساعت', value: '2 hours' }, // localized
    						{ label: '۳ ساعت', value: '3 hours' }, // localized
    						{ label: '۶ ساعت', value: '6 hours' }, // localized
    						{ label: '۱۲ ساعت', value: '12 hours' }, // localized
    						{ label: '۱ روز', value: '1 day' }, // localized
    						{ label: '۲ روز', value: '2 days' }, // localized
    						{ label: '۳ روز', value: '3 days' }, // localized
    						{ label: '۴ روز', value: '4 days' }, // localized
    						{ label: '۱ هفته', value: '1 week' }, // localized
    						{ label: '۲ هفته', value: '2 weeks' }, // localized
    						{ label: '۱ ماه', value: '1 month' }, // localized
    						{ label: '۲ ماه', value: '2 months' }, // localized
    						{ label: '۳ ماه', value: '3 months' }, // localized
    						{ label: '۱ سال', value: '1 year' }, // localized
    						{ label: 'بی‌پایان', value: 'indefinite' }, // localized
    						{ label: 'دلخواه', value: 'custom' } // localized
    					]
    				});
    				// Namespaces hardcoded until [[phab:T218479]]
    				if (mw.loader.getState('ext.flaggedRevs.review') && (mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 4)) {
    					field2.append({
    						type: 'checkbox',
    						name: 'pcmodify',
    						event: Twinkle.protect.formevents.pcmodify,
    						list: [
    							{
    								label: 'تغییر حفاظت نیازمند بازبینی', // localized
    								value: 'pcmodify',
    								tooltip: 'اگر این جعبه خاموش باشد، سطح حفاظت نیازمند بازبینی و زمان سرآمدن به همان شکلی که هستند باقی می‌مانند', // localized
    								checked: true
    							}
    						]
    					});
    					var pclevel = field2.append({
    						type: 'select',
    						name: 'pclevel',
    						label: 'تغییرات درحال انتظار:', // localized
    						event: Twinkle.protect.formevents.pclevel
    					});
    					pclevel.append({
    						type: 'option',
    						label: 'هیچ', // localized
    						value: 'none'
    					});
    					pclevel.append({
    						type: 'option',
    						label: 'تغییرات در حال انتظار', // localized
    						value: 'autoconfirmed',
    						selected: true
    					});
    					field2.append({
    						type: 'select',
    						name: 'pcexpiry',
    						label: 'سرآمدن:', // localized
    						event: function(e) {
    							if (e.target.value === 'custom') {
    								Twinkle.protect.doCustomExpiry(e.target);
    							}
    						},
    						list: [
    							{ label: '۱ ساعت', value: '1 hour' }, // localized
    							{ label: '۲ ساعت', value: '2 hours' }, // localized
    							{ label: '۳ ساعت', value: '3 hours' }, // localized
    							{ label: '۶ ساعت', value: '6 hours' }, // localized
    							{ label: '۱۲ ساعت', value: '12 hours' }, // localized
    							{ label: '۱ روز', value: '1 day' }, // localized
    							{ label: '۲ روز', value: '2 days' }, // localized
    							{ label: '۳ روز', value: '3 days' }, // localized
    							{ label: '۴ روز', value: '4 days' }, // localized
    							{ label: '۱ هفته', value: '1 week' }, // localized
    							{ label: '۲ هفته', value: '2 weeks' }, // localized
    							{ label: '۱ ماه', selected: true, value: '1 month' }, // localized
    							{ label: '۲ ماه', value: '2 months' }, // localized
    							{ label: '۳ ماه', value: '3 months' }, // localized
    							{ label: '۱ سال', value: '1 year' }, // localized
    							{ label: 'بی‌پایان', value: 'indefinite' }, // localized
    							{ label: 'دلخواه', value: 'custom' } // localized
    						]
    					});
    				}
    			} else {  // for non-existing pages
    				var createlevel = field2.append({
    					type: 'select',
    					name: 'createlevel',
    					label: 'حفاظت در برابر ایجاد:', // localized
    					event: Twinkle.protect.formevents.createlevel
    				});
    				createlevel.append({
    					type: 'option',
    					label: 'همه', // localized
    					value: 'all'
    				});
    				if (mw.config.get('wgNamespaceNumber') !== 0) {
    					createlevel.append({
    						type: 'option',
    						label: 'تأیید خودکار', // localized
    						value: 'autoconfirmed'
    					});
    				}
    				if (isTemplate) {
    					createlevel.append({
    						type: 'option',
    						label: 'ویرایشگر الگو', // localized
    						value: 'templateeditor'
    					});
    				}
    				createlevel.append({
    					type: 'option',
    					label: 'تأییدشدهٔ پایدار', // localized
    					value: 'extendedconfirmed',
    					selected: true
    				});
    				createlevel.append({
    					type: 'option',
    					label: 'مدیر', // localized
    					value: 'sysop'
    				});
    				field2.append({
    					type: 'select',
    					name: 'createexpiry',
    					label: 'سرآمدن:', // localized
    					event: function(e) {
    						if (e.target.value === 'custom') {
    							Twinkle.protect.doCustomExpiry(e.target);
    						}
    					},
    					list: [
    						{ label: '۱ ساعت', value: '1 hour' }, // localized
    						{ label: '۲ ساعت', value: '2 hours' }, // localized
    						{ label: '۳ ساعت', value: '3 hours' }, // localized
    						{ label: '۶ ساعت', value: '6 hours' }, // localized
    						{ label: '۱۲ ساعت', value: '12 hours' }, // localized
    						{ label: '۱ روز', value: '1 day' }, // localized
    						{ label: '۲ روز', value: '2 days' }, // localized
    						{ label: '۳ روز', value: '3 days' }, // localized
    						{ label: '۴ روز', value: '4 days' }, // localized
    						{ label: '۱ هفته', value: '1 week' }, // localized
    						{ label: '۲ هفته', value: '2 weeks' }, // localized
    						{ label: '۱ ماه', value: '1 month' }, // localized
    						{ label: '۲ ماه', value: '2 months' }, // localized
    						{ label: '۳ ماه', value: '3 months' }, // localized
    						{ label: '۱ سال', value: '1 year' }, // localized
    						{ label: 'بی‌پایان', selected: true, value: 'indefinite' }, // localized
    						{ label: 'دلخواه', value: 'custom' } // localized
    					]
    				});
    			}
    			field2.append({
    				type: 'textarea',
    				name: 'protectReason',
    				label: 'دلیل (برای سیاههٔ محافظت):' // localized
    			});
    			if (!mw.config.get('wgArticleId') || mw.config.get('wgPageContentModel') === 'Scribunto') {  // tagging isn't relevant for non-existing or module pages
    				break;
    			}
    			/* falls through */
    		case 'tag':
    			field1 = new Morebits.quickForm.element({ type: 'field', label: 'گزینه‌های برچسب زدن', name: 'field1' });
    			field1.append({ type: 'div', name: 'currentprot', label: ' ' });  // holds the current protection level, as filled out by the async callback
    			field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
    			field1.append({
    				type: 'select',
    				name: 'tagtype',
    				label: 'انتخاب الگوی محافظت:', // localized
    				list: Twinkle.protect.protectionTags,
    				event: Twinkle.protect.formevents.tagtype
    			});
    			field1.append({
    				type: 'checkbox',
    				list: [
    					{
    						name: 'small',
    						label: 'کوچک (small=yes)', // localized
    						tooltip: 'استفاده از ویژگی |small=yes  الگو، به شکلی که فقط قفل نمایش داده شود', // localized
    						checked: true
    					},
    					{
    						name: 'noinclude',
    						label: 'قراردادن الگوی حفاظت درون برچسب <noinclude>', // localized
    						tooltip: 'الگوی حفاظت را درون &lt;noinclude&gt; قرار می‌دهد تا تراگنجانش نشود', // localized
    						checked: mw.config.get('wgNamespaceNumber') === 10
    					}
    				]
    			});
    			break;

    		case 'request':
    			field_preset = new Morebits.quickForm.element({ type: 'field', label: 'نوع محافظت', name: 'field_preset' }); // localized
    			field_preset.append({
    				type: 'select',
    				name: 'category',
    				label: 'نوع و دلیل:', // localized
    				event: Twinkle.protect.callback.changePreset,
    				list: mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate
    			});

    			field1 = new Morebits.quickForm.element({ type: 'field', label: 'گزینه‌ها', name: 'field1' }); // localized
    			field1.append({ type: 'div', name: 'currentprot', label: ' ' });  // holds the current protection level, as filled out by the async callback
    			field1.append({ type: 'div', name: 'hasprotectlog', label: ' ' });
    			field1.append({
    				type: 'select',
    				name: 'expiry',
    				label: 'مدت: ', // localized
    				list: [
    					{ label: 'موقت', value: 'temporary' }, // localized
    					{ label: 'بی‌پایان', value: 'indefinite' },  // localized
    					{ label: '', selected: true, value: '' }
    				]
    			});
    			field1.append({
    				type: 'textarea',
    				name: 'reason',
    				label: 'دلیل: '  // localized
    			});
    			break;
    		default:
    			alert("مشکلی در حین اجرای حفاظت توینکلی پیش آمد"); // localized
    			break;
    	}

    	var oldfield;

    	if (field_preset) {
    		oldfield = $(e.target.form).find('fieldset[name="field_preset"]')[0];
    		oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
    	} else {
    		$(e.target.form).find('fieldset[name="field_preset"]').css('display', 'none');
    	}
    	if (field1) {
    		oldfield = $(e.target.form).find('fieldset[name="field1"]')[0];
    		oldfield.parentNode.replaceChild(field1.render(), oldfield);
    	} else {
    		$(e.target.form).find('fieldset[name="field1"]').css('display', 'none');
    	}
    	if (field2) {
    		oldfield = $(e.target.form).find('fieldset[name="field2"]')[0];
    		oldfield.parentNode.replaceChild(field2.render(), oldfield);
    	} else {
    		$(e.target.form).find('fieldset[name="field2"]').css('display', 'none');
    	}

    	if (e.target.values === 'protect') {
    		// fake a change event on the preset dropdown
    		var evt = document.createEvent('Event');
    		evt.initEvent('change', true, true);
    		e.target.form.category.dispatchEvent(evt);

    		// reduce vertical height of dialog
    		$(e.target.form).find('fieldset[name="field2"] select').parent().css({ display: 'inline-block', marginRight: '0.5em' });
    	}

    	// re-add protection level and log info, if it's available
    	Twinkle.protect.callback.showLogAndCurrentProtectInfo();
    };

    Twinkle.protect.formevents = {
    	editmodify: function twinkleprotectFormEditmodifyEvent(e) {
    		e.target.form.editlevel.disabled = !e.target.checked;
    		e.target.form.editexpiry.disabled = !e.target.checked || (e.target.form.editlevel.value === 'all');
    		e.target.form.editlevel.style.color = e.target.form.editexpiry.style.color = e.target.checked ? '' : 'transparent';
    	},
    	editlevel: function twinkleprotectFormEditlevelEvent(e) {
    		e.target.form.editexpiry.disabled = e.target.value === 'all';
    	},
    	movemodify: function twinkleprotectFormMovemodifyEvent(e) {
    		// sync move settings with edit settings if applicable
    		if (e.target.form.movelevel.disabled && !e.target.form.editlevel.disabled) {
    			e.target.form.movelevel.value = e.target.form.editlevel.value;
    			e.target.form.moveexpiry.value = e.target.form.editexpiry.value;
    		} else if (e.target.form.editlevel.disabled) {
    			e.target.form.movelevel.value = 'sysop';
    			e.target.form.moveexpiry.value = 'indefinite';
    		}
    		e.target.form.movelevel.disabled = !e.target.checked;
    		e.target.form.moveexpiry.disabled = !e.target.checked || (e.target.form.movelevel.value === 'all');
    		e.target.form.movelevel.style.color = e.target.form.moveexpiry.style.color = e.target.checked ? '' : 'transparent';
    	},
    	movelevel: function twinkleprotectFormMovelevelEvent(e) {
    		e.target.form.moveexpiry.disabled = e.target.value === 'all';
    	},
    	pcmodify: function twinkleprotectFormPcmodifyEvent(e) {
    		e.target.form.pclevel.disabled = !e.target.checked;
    		e.target.form.pcexpiry.disabled = !e.target.checked || (e.target.form.pclevel.value === 'none');
    		e.target.form.pclevel.style.color = e.target.form.pcexpiry.style.color = e.target.checked ? '' : 'transparent';
    	},
    	pclevel: function twinkleprotectFormPclevelEvent(e) {
    		e.target.form.pcexpiry.disabled = e.target.value === 'none';
    	},
    	createlevel: function twinkleprotectFormCreatelevelEvent(e) {
    		e.target.form.createexpiry.disabled = e.target.value === 'all';
    	},
    	tagtype: function twinkleprotectFormTagtypeEvent(e) {
    		e.target.form.small.disabled = e.target.form.noinclude.disabled = (e.target.value === 'none') || (e.target.value === 'noop');
    	}
    };

    Twinkle.protect.doCustomExpiry = function twinkleprotectDoCustomExpiry(target) {
    	var custom = prompt('یک زمان سرآمدن سفارشی وارد کنید. \n می‌توانید زمان‌های نسبی مثل «۱ دقیقه» یا «۱۹ روز» یا زمان‌مهر مطلق به شکل yyyymmddhhmm وارد کنید (به عنوان مثال "200602011405" نشان دهندهٔ اول فوریهٔ ۲۰۰۶، ساعت ۱۴:۰۵ جهانی است).', ''); // localized fixes might be necessary
    	if (custom) {
    		var option = document.createElement('option');
    		option.setAttribute('value', custom);
    		option.textContent = custom;
    		target.appendChild(option);
    		target.value = custom;
    	} else {
    		target.selectedIndex = 0;
    	}
    };

    Twinkle.protect.protectionTypes = [
    	{ label: 'خروج از حفاظت', value: 'unprotect' }, // localized
    	{
    		label: 'حفاظت کامل', // localized
    		list: [
    			{ label: 'کلی (کامل)', value: 'pp-protected' }, // localized
    			{ label: 'اختلاف نظر / جنگ ویرایشی (کامل)', value: 'pp-dispute' }, // localized
    			{ label: 'خرابکاری مداوم (کامل)', value: 'pp-vandalism' }, // localized
    			{ label: 'بحث کاربری بسته‌شده (کامل)', value: 'pp-usertalk' } // localized
    		]
    	},
    	{
    		label: 'حفاظت الگو', // localized
    		list: [
    			{ label: 'الگوی پرکاربرد', value: 'pp-template' } // localized
    		]
    	},
    	{
    		label: 'محافظت در حد تأییدشدهٔ پایدار', // localized
    		list: [
    			{ label: 'تصمیم هیئت داوری', selected: true, value: 'pp-30-500-arb' }, // localized
    			{ label: 'خرابکاری پی‌درپی', value: 'pp-30-500-vandalism' }, // localized
    			{ label: 'ویرایش فلج‌کننده', value: 'pp-30-500-disruptive' }, // localized
    			{ label: 'سرپیچی از سیاست زندگی‌نامهٔ زندگان', value: 'pp-30-500-blp' }, // localized
    			{ label: 'زاپاس‌بازی', value: 'pp-30-500-sock' } // localized
    		]
    	},
    	{
    		label: 'نیمه‌محافظت', // localized
    		list: [
    			{ label: 'کلی (نیمه‌حفاظت)', value: 'pp-semi-protected' }, // localized
    			{ label: 'خرابکاری ادامه‌دار (نیمه‌حفاظت)', selected: true, value: 'pp-semi-vandalism' }, // localized
    			{ label: 'ویرایش فلج‌کننده (نیمه‌حفاظت)', value: 'pp-semi-disruptive' }, // localized
    			{ label: 'افزودن مطالب بدون منبع (نیمه حفاظت)', value: 'pp-semi-unsourced' }, // localized
    			{ label: 'سرپیچی از سیاست زندگی‌نامهٔ زندگان (نیمه‌حفاظت)', value: 'pp-semi-blp' }, // localized
    			{ label: 'زاپاس‌بازی (نیمه‌حفاظت)', value: 'pp-semi-sock' }, // localized
    			{ label: 'صفحهٔ بحث کاربر بسته‌شده (نیمه‌حفاظت)', value: 'pp-semi-usertalk' } // localized
    		]
    	},
    	{
    		label: 'تغییرات در حال انتظار', // localized
    		list: [
    			{ label: 'کلی', value: 'pp-pc-protected' }, // localized
    			{ label: 'خرابکاری پی‌درپی', value: 'pp-pc-vandalism' }, // localized
    			{ label: 'ویرایش فلج‌کننده', value: 'pp-pc-disruptive' }, // localized
    			{ label: 'افزودن مطالب بی‌منبع', value: 'pp-pc-unsourced' }, // localized
    			{ label: 'سرپیچی از سیاست زندگی‌نامهٔ زندگان', value: 'pp-pc-blp' } // localized
    		]
    	},
    	{
    		label: 'حفاظت از انتقال', // localized
    		list: [
    			{ label: 'کلی (انتقال)', value: 'pp-move' }, // localized
    			{ label: 'اختلاف نظر/جنگ برسر عنوان (انتقال)', value: 'pp-move-dispute' }, // localized
    			{ label: 'خرابکاری از طریق انتقال (انتقال)', value: 'pp-move-vandalism' }, // localized
    			{ label: 'صفحهٔ پربازدید (انتقال)', value: 'pp-move-indef' } // localized
    		]
    	}
    ];

    Twinkle.protect.protectionTypesCreate = [
    	{ label: 'خروج از محافظت', value: 'unprotect' }, // localized
    	{
    		label: 'محافظت در برابر ایجاد', // localized
    		list: [
    			{ label: 'کلی ({{pp-create}})', value: 'pp-create' }, // localized
    			{ label: 'نام نامناسب', value: 'pp-create-offensive' }, // localized
    			{ label: 'ایجادهای مجدد', selected: true, value: 'pp-create-salt' }, // localized
    			{ label: 'زندگی‌نامهٔ زندگان که یه تازگی حذف‌شده', value: 'pp-create-blp' } // localized
    		]
    	}
    ];

    // A page with both regular and PC protection will be assigned its regular
    // protection weight plus 2
    Twinkle.protect.protectionWeight = {
    	sysop: 40,
    	templateeditor: 30,
    	extendedconfirmed: 20,
    	autoconfirmed: 10,
    	flaggedrevs_autoconfirmed: 5,  // Pending Changes protection alone
    	all: 0,
    	flaggedrevs_none: 0  // just in case
    };

    // NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
    // Also note: stabilize = Pending Changes level
    Twinkle.protect.protectionPresetsInfo = {
    	'pp-protected': {
    		edit: 'sysop',
    		move: 'sysop',
    		reason: null
    	},
    	'pp-dispute': {
    		edit: 'sysop',
    		move: 'sysop',
    		reason: '[[وپ:مناقشه|مناقشه بر سر محتوا/جنگ ویرایشی]]' // localized
    	},
    	'pp-vandalism': {
    		edit: 'sysop',
    		move: 'sysop',
    		reason: '[[وپ:خ|خرابکاری]] ادامه‌دار' // localized
    	},
    	'pp-usertalk': {
    		edit: 'sysop',
    		move: 'sysop',
    		reason: '[[وپ:حبک|استفادهٔ نادرست از صفحهٔ بحث کاربر در حین بندایش]]' // localized
    	},
    	'pp-template': {
    		edit: 'templateeditor',
    		move: 'templateeditor',
    		reason: '[[وپ:حساس|الگوهای بسیار پرکاربرد]]' // localized
    	},
    	'pp-30-500-arb': {
    		edit: 'extendedconfirmed',
    		move: 'extendedconfirmed',
    		reason: '[[وپ:قفل آبی|درخواست هیئت نظارت]]',
    		template: 'pp-30-500'
    	},
    	'pp-30-500-vandalism': {
    		edit: 'extendedconfirmed',
    		move: 'extendedconfirmed',
    		reason: ' [[وپ:خ|خرابکاری]] ادامه‌دار از سوی حساب‌های تأیید‌شده(ی‌خودکار)', // localized
    		template: 'pp-30-500'
    	},
    	'pp-30-500-disruptive': {
    		edit: 'extendedconfirmed',
    		move: 'extendedconfirmed',
    		reason: '[[وپ:اخلال|ویرایش اخلالگرانهٔ]] ادامه‌دار توسط کاربران تأیید شده', // localized
    		template: 'pp-30-500'
    	},
    	'pp-30-500-blp': {
    		edit: 'extendedconfirmed',
    		move: 'extendedconfirmed',
    		reason: 'نقض ادامه‌دار [[وپ:زز|سیاست زندگی‌نامه زندگان]] توسط کاربران تأیید شده', // localized
    		template: 'pp-30-500'
    	},
    	'pp-30-500-sock': {
    		edit: 'extendedconfirmed',
    		move: 'extendedconfirmed',
    		reason: 'Persistent [[وپ:زاپاس|زاپاس بازی]]', // localized
    		template: 'pp-30-500'
    	},
    	'pp-semi-vandalism': {
    		edit: 'autoconfirmed',
    		reason: '[[وپ:خرابکاری|خرابکاری]] ادامه‌دار', // localized
    		template: 'pp-vandalism'
    	},
    	'pp-semi-disruptive': {
    		edit: 'autoconfirmed',
    		reason: '[[وپ:اخلال|ویرایش اخلالگرانهٔ]] ادامه‌دار', // localized
    		template: 'pp-protected'
    	},
    	'pp-semi-unsourced': {
    		edit: 'autoconfirmed',
    		reason: 'افزودن مداوم [[WP:INTREF|مطالب بدون منبع یا با منبع نامعتبر]]', // localized
    		template: 'pp-protected'
    	},
    	'pp-semi-blp': {
    		edit: 'autoconfirmed',
    		reason: 'نقض [[وپ:زنز|سیاست زندگی‌نامهٔ زندگان]]',
    		template: 'pp-blp'
    	},
    	'pp-semi-usertalk': {
    		edit: 'autoconfirmed',
    		move: 'autoconfirmed',
    		reason: '[[وپ:حفاظت#فضای نام بحث کاربر|استفادهٔ نادرست از صفحهٔ بحث کاربری در زمان بسته بودن]]',
    		template: 'pp-usertalk'
    	},
    	'pp-semi-template': {  // removed for now
    		edit: 'autoconfirmed',
    		move: 'autoconfirmed',
    		reason: '[[ویکی‌پدیا:الگوهای حساس|الگوی حساس]]',
    		template: 'pp-template'
    	},
    	'pp-semi-sock': {
    		edit: 'autoconfirmed',
    		reason: '[[وپ:زاپاس‌بازی|زاپاس‌بازی]] ادامه‌دار',
    		template: 'pp-sock'
    	},
    	'pp-semi-protected': {
    		edit: 'autoconfirmed',
    		reason: null,
    		template: 'pp-protected'
    	},
    	'pp-pc-vandalism': {
    		stabilize: 'autoconfirmed',  // stabilize = Pending Changes
    		reason: '[[:خرابکاری|خرابکاری]] ادامه‌دار', // localized
    		template: 'pp-pc'
    	},
    	'pp-pc-disruptive': {
    		stabilize: 'autoconfirmed',
    		reason: '[[وپ:اخلال|ویرایش‌های اخلالگرانه]] ادامه‌دار', // localized
    		template: 'pp-pc'
    	},
    	'pp-pc-unsourced': {
    		stabilize: 'autoconfirmed',
    		reason: 'ادامه‌دار بودن [[وپ:مقدارج|افزودن مداوم مطالب بدون منبع یا منبع ضعیف]]', // localized
    		template: 'pp-pc'
    	},
    	'pp-pc-blp': {
    		stabilize: 'autoconfirmed',
    		reason: 'نقض [[وپ:زنده|سیاست زندگی‌نامه زندگان]]', // localized
    		template: 'pp-pc'
    	},
    	'pp-pc-protected': {
    		stabilize: 'autoconfirmed',
    		reason: null,
    		template: 'pp-pc'
    	},
    	'pp-move': {
    		move: 'sysop',
    		reason: null
    	},
    	'pp-move-dispute': {
    		move: 'sysop',
    		reason: '[[وپ:قفل سبز|مناقشه بر سر نام]]' // localized
    	},
    	'pp-move-vandalism': {
    		move: 'sysop',
    		reason: '[[وپ:قفل سبز|خرابکاری از طریق انتقال]]' // localized
    	},
    	'pp-move-indef': {
    		move: 'sysop',
    		reason: '[[وپ:قفل سبز|صفحهٔ پربیننده]]' // localized
    	},
    	'unprotect': {
    		edit: 'all',
    		move: 'all',
    		stabilize: 'none',
    		create: 'all',
    		reason: null,
    		template: 'none'
    	},
    	'pp-create-offensive': {
    		create: 'sysop',
    		reason: '[[وپ:نمک|نام نامناسب]]' // localized
    	},
    	'pp-create-salt': {
    		create: 'extendedconfirmed',
    		reason: '[[وپ:نمک|ایجاد پیاپی]]' // localized
    	},
    	'pp-create-blp': {
    		create: 'extendedconfirmed',
    		reason: '[[وپ:حزنز|زندگی‌نامهٔ اخیراً حذف‌شده]]'
    	},
    	'pp-create': {
    		create: 'extendedconfirmed',
    		reason: '{{pp-create}}' // localized version to be decided, non-existing in source
    	}
    };

    Twinkle.protect.protectionTags = [
    	{
    		label: 'هیچ (حذف الگوهای حفاظت فعلی)', // localized
    		value: 'none'
    	},
    	{
    		label: 'هیچ (بدون حذف الگوهای حفاظت فعلی)', // localized
    		value: 'noop'
    	},
    	{
    		label: 'الگوهای حفاظت دربرابر ویرایش', // localized
    		list: [
    			{ label: '{{pp-vandalism}}: خرابکاری', value: 'pp-vandalism' }, // localized
    			{ label: '{{pp-dispute}}: مناقشه/جنگ ویرایشی', value: 'pp-dispute' }, // localized
    			{ label: '{{pp-blp}}: سرپیچی از سیاست زندگی‌نامهٔ زندگان', value: 'pp-blp' }, // localized
    			{ label: '{{pp-sock}}: زاپاس‌بازی', value: 'pp-sock' }, // localized
    			{ label: '{{pp-template}}: الگوی حساس', value: 'pp-template' }, // localized
    			{ label: '{{pp-usertalk}}: صفحهٔ بحث کاربر بسته‌شده', value: 'pp-usertalk' }, // localized
    			{ label: '{{pp-protected}}: حفاظت کلی', value: 'pp-protected' }, // localized
    			{ label: '{{pp-semi-indef}}: نیمه‌حفاظت کلی و طولانی‌مدت', value: 'pp-semi-indef' }, // localized
    			{ label: '{{pp-30-500}}: نیمه‌حفاظت ویژه', value: 'pp-30-500' } // localized
    		]
    	},
    	{
    		label: 'الگوهای تغییرات درحال انتظار', // localized
    		list: [
    			{ label: '{{pp-pc}}: تغییرات در حال انتظار', value: 'pp-pc' } // localized
    		]
    	},
    	{
    		label: 'الگوهای حفاظت در برابر انتقال', // localized
    		list: [
    			{ label: '{{pp-move-dispute}}: مناقشه/جنگ بر سر انتقال', value: 'pp-move-dispute' }, // localized
    			{ label: '{{pp-move-vandalism}}: خرابکاری از طریق انتقال', value: 'pp-move-vandalism' }, // localized
    			{ label: '{{pp-move-indef}}: کلی و طولانی‌مدت', value: 'pp-move-indef' }, // localized
    			{ label: '{{pp-move}}: سایر', value: 'pp-move' } // localized
    		]
    	}
    ];

    Twinkle.protect.callback.changePreset = function twinkleprotectCallbackChangePreset(e) {
    	var form = e.target.form;

    	var actiontypes = form.actiontype;
    	var actiontype;
    	for (var i = 0; i < actiontypes.length; i++) {
    		if (!actiontypes[i].checked) {
    			continue;
    		}
    		actiontype = actiontypes[i].values;
    		break;
    	}

    	if (actiontype === 'protect') {  // actually protecting the page
    		var item = Twinkle.protect.protectionPresetsInfo[form.category.value];

    		if (mw.config.get('wgArticleId')) {
    			if (item.edit) {
    				form.editmodify.checked = true;
    				Twinkle.protect.formevents.editmodify({ target: form.editmodify });
    				form.editlevel.value = item.edit;
    				Twinkle.protect.formevents.editlevel({ target: form.editlevel });
    				form.editexpiry.value = '2 days';
    			} else {
    				form.editmodify.checked = false;
    				Twinkle.protect.formevents.editmodify({ target: form.editmodify });
    			}

    			if (item.move) {
    				form.movemodify.checked = true;
    				Twinkle.protect.formevents.movemodify({ target: form.movemodify });
    				form.movelevel.value = item.move;
    				Twinkle.protect.formevents.movelevel({ target: form.movelevel });
    				form.moveexpiry.value = '2 days';
    			} else {
    				form.movemodify.checked = false;
    				Twinkle.protect.formevents.movemodify({ target: form.movemodify });
    			}

    			if (form.pcmodify) {
    				if (item.stabilize) {
    					form.pcmodify.checked = true;
    					Twinkle.protect.formevents.pcmodify({ target: form.pcmodify });
    					form.pclevel.value = item.stabilize;
    					Twinkle.protect.formevents.pclevel({ target: form.pclevel });
    				} else {
    					form.pcmodify.checked = false;
    					Twinkle.protect.formevents.pcmodify({ target: form.pcmodify });
    				}
    			}
    		} else {
    			if (item.create) {
    				form.createlevel.value = item.create;
    				Twinkle.protect.formevents.createlevel({ target: form.createlevel });
    			}
    		}

    		var reasonField = actiontype === 'protect' ? form.protectReason : form.reason;
    		if (item.reason) {
    			reasonField.value = item.reason;
    		} else {
    			reasonField.value = '';
    		}

    		// sort out tagging options, disabled if nonexistent or lua
    		if (mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto') {
    			if (form.category.value === 'unprotect') {
    				form.tagtype.value = 'none';
    			} else {
    				form.tagtype.value = item.template ? item.template : form.category.value;
    			}
    			Twinkle.protect.formevents.tagtype({ target: form.tagtype });

    			if (/template/.test(form.category.value)) {
    				form.noinclude.checked = true;
    				form.editexpiry.value = form.moveexpiry.value = form.pcexpiry.value = 'indefinite';
    			} else if (mw.config.get('wgNamespaceNumber') !== 10) {
    				form.noinclude.checked = false;
    			}
    		}

    	} else {  // RPP request
    		if (form.category.value === 'unprotect') {
    			form.expiry.value = '';
    			form.expiry.disabled = true;
    		} else {
    			form.expiry.value = '';
    			form.expiry.disabled = false;
    		}
    	}
    };

    Twinkle.protect.callback.evaluate = function twinkleprotectCallbackEvaluate(e) {
    	var form = e.target;

    	var actiontypes = form.actiontype;
    	var actiontype;
    	for (var i = 0; i < actiontypes.length; i++) {
    		if (!actiontypes[i].checked) {
    			continue;
    		}
    		actiontype = actiontypes[i].values;
    		break;
    	}

    	var tagparams;
    	if (actiontype === 'tag' || (actiontype === 'protect' && mw.config.get('wgArticleId') && mw.config.get('wgPageContentModel') !== 'Scribunto')) {
    		tagparams = {
    			tag: form.tagtype.value,
    			reason: (form.tagtype.value === 'pp-protected' || form.tagtype.value === 'pp-semi-protected' || form.tagtype.value === 'pp-move') && form.protectReason ? form.protectReason.value : null,
    			small: form.small.checked,
    			noinclude: form.noinclude.checked
    		};
    	}

    	switch (actiontype) {
    		case 'protect':
    			// protect the page
    			Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
    			Morebits.wiki.actionCompleted.notice = 'محافظت کامل شد'; // localized

    			var statusInited = false;
    			var thispage;

    			var allDone = function twinkleprotectCallbackAllDone() {
    				if (thispage) {
    					thispage.getStatusElement().info('done');
    				}
    				if (tagparams) {
    					Twinkle.protect.callbacks.taggingPageInitial(tagparams);
    				}
    			};

    			var stabilizeValues = {};
    			if (form.pclevel) {
    				stabilizeValues = {
    					pclevel: form.pclevel.value,
    					pcexpiry: form.pcexpiry.value,
    					protectReason: form.protectReason.value
    				};
    			}

    			var protectIt = function twinkleprotectCallbackProtectIt(next) {
    				thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), ' محافظت صفحه'); // localized
    				if (mw.config.get('wgArticleId')) {
    					if (form.editmodify.checked) {
    						thispage.setEditProtection(form.editlevel.value, form.editexpiry.value);
    					}
    					if (form.movemodify.checked) {
    						thispage.setMoveProtection(form.movelevel.value, form.moveexpiry.value);
    					}
    				} else {
    					thispage.setCreateProtection(form.createlevel.value, form.createexpiry.value);
    					thispage.setWatchlist(false);
    				}

    				if (form.protectReason.value) {
    					thispage.setEditSummary(form.protectReason.value);
    				} else {
    					alert('می‌بایست دلیلی برای حفاظت جهت ذکر در سیاههٔ محافظت ارائه دهید.'); // localized
    					return;
    				}

    				if (!statusInited) {
    					Morebits.simpleWindow.setButtonsEnabled(false);
    					Morebits.status.init(form);
    					statusInited = true;
    				}

    				thispage.protect(next);
    			};

    			var stabilizeIt = function twinkleprotectCallbackStabilizeIt() {
    				if (thispage) {
    					thispage.getStatusElement().info('done');
    				}

    				thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'اعمال حفاظت نیازمند بازبینی');
    				thispage.setFlaggedRevs(stabilizeValues.pclevel, stabilizeValues.pcexpiry);

    				if (stabilizeValues.protectReason) {
    					thispage.setEditSummary(stabilizeValues.protectReason);
    				} else {
    					alert('باید دلیلی برای درخواست ذکر کنید تا در سیاهه محافظت ثبت شود.'); // localized
    					return;
    				}

    				if (!statusInited) {
    					Morebits.simpleWindow.setButtonsEnabled(false);
    					Morebits.status.init(form);
    					statusInited = true;
    				}

    				thispage.stabilize(allDone, function(error) {
    					if (error.errorCode === 'stabilize_denied') { // [[phab:T234743]]
    						thispage.getStatusElement().error('ناموفق در زمان تلاش برای تغییر تنظیمان حفاظت نیازمند بازبینی، که احتمالاً به‌دلیل وجود مشکل در نرم‌افزار مدیاویکی است. سایر کنش‌ها (برچسب‌زدن یا محافظت‌های معمول) ممکن است انجام شده‌باشند. لطفاً صفحه را تازه‌سازی کنید و دوباره تلاش کنید.');
    					}
    				});
    			};

    			if ((form.editmodify && form.editmodify.checked) || (form.movemodify && form.movemodify.checked) ||
    				!mw.config.get('wgArticleId')) {
    				if (form.pcmodify && form.pcmodify.checked) {
    					protectIt(stabilizeIt);
    				} else {
    					protectIt(allDone);
    				}
    			} else if (form.pcmodify && form.pcmodify.checked) {
    				stabilizeIt();
    			} else {
    				alert("لطفا دستوری به توینکل دهید.\nاگر صرفا قصد برچسب‌زدن دارید، گزینهٔ 'برچسب زدن صفحه' را از بالاانتخاب کنید."); // localized
    			}

    			break;

    		case 'tag':
    			// apply a protection template

    			Morebits.simpleWindow.setButtonsEnabled(false);
    			Morebits.status.init(form);

    			Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
    			Morebits.wiki.actionCompleted.followRedirect = false;
    			Morebits.wiki.actionCompleted.notice = 'برچسب زدن کامل شد'; // localized

    			Twinkle.protect.callbacks.taggingPageInitial(tagparams);
    			break;

    		case 'request':
    			// file request at RFPP
    			var typename, typereason;
    			switch (form.category.value) {
    				case 'pp-dispute':
    				case 'pp-vandalism':
    				case 'pp-usertalk':
    				case 'pp-protected':
    					typename = 'حفاظت کامل'; // localized
    					break;
    				case 'pp-template':
    						typename = 'حفاظت الگو'; // localized
    					break;
    				case 'pp-30-500-arb':
    				case 'pp-30-500-vandalism':
    				case 'pp-30-500-disruptive':
    				case 'pp-30-500-blp':
    				case 'pp-30-500-sock':
    					typename = 'نیمه‌حفاظت‌شدهٔ ویژه'; // localized
    					break;
    				case 'pp-semi-vandalism':
    				case 'pp-semi-disruptive':
    				case 'pp-semi-unsourced':
    				case 'pp-semi-usertalk':
    				case 'pp-semi-sock':
    				case 'pp-semi-blp':
    				case 'pp-semi-protected':
    					typename = 'نیمه‌حفاظت'; // localized
    					break;
    				case 'pp-pc-vandalism':
    				case 'pp-pc-blp':
    				case 'pp-pc-protected':
    				case 'pp-pc-unsourced':
    				case 'pp-pc-disruptive':
    					typename = 'نیازمند بازبینی'; // localized
    					break;
    				case 'pp-move':
    				case 'pp-move-dispute':
    				case 'pp-move-indef':
    				case 'pp-move-vandalism':
    					typename = 'حفاظت در برابر انتقال'; // localized
    					break;
    				case 'pp-create':
    				case 'pp-create-offensive':
    				case 'pp-create-blp':
    				case 'pp-create-salt':
    					typename = 'حفاظت در برابر ایجاد'; // localized
    					break;
    				case 'unprotect':
    					var admins = $.map(Twinkle.protect.currentProtectionLevels, function(pl) {
    						return pl.admin ? 'کاربر:' + pl.admin : null;
    					});
    					if (admins.length && !confirm('آیا قبلا با مدیران حفاظت کننده (' + $.unique(admins).join('، ') + ') تماس گرفته‌اید؟')) { // localized
    						return false;
    					}
    					// otherwise falls through
    				default:
    					typename = 'unprotection';
    					break;
    			}
    			switch (form.category.value) {
    				case 'pp-dispute':
    					typereason = 'مناقشه بر سر محتوا/جنگ ویرایشی'; // localized
    					break;
    				case 'pp-vandalism':
    				case 'pp-semi-vandalism':
    				case 'pp-pc-vandalism':
    				case 'pp-30-500-vandalism':
    					typereason = ' [[وپ:خ|خرابکاری]] ادامه‌دار'; // localized
    					break;
    				case 'pp-semi-disruptive':
    				case 'pp-pc-disruptive':
    				case 'pp-30-500-disruptive':
    					typereason = ' [[وپ:اخلال|ویرایش اخلالگرانهٔ]] ادامه‌دار'; // localized
    					break;
    				case 'pp-semi-unsourced':
    				case 'pp-pc-unsourced':
    					typereason = '[[وپ:مقدارج|مطالب بدون منبع]] افزودن ادامه‌دار'; // localized
    					break;
    				case 'pp-template':
    					typereason = '[[وپ:حساس|الگوی حساس]]'; // localized
    					break;
    				case 'pp-30-500-arb':
    					typereason = '[[وپ:۳۰/۵۰۰|تصمیم هیئت داوری]]'; // localized
    					break;
    				case 'pp-usertalk':
    				case 'pp-semi-usertalk':
    					typereason = 'استفادهٔ نادرست از صفحهٔ بحث کاربر در حین بندایش'; // localized
    					break;
    				case 'pp-semi-sock':
    				case 'pp-30-500-sock':
    					typereason = '[[وپ:ز|زاپاس‌بازی]] ادامه‌دار'; // localized
    					break;
    				case 'pp-semi-blp':
    				case 'pp-pc-blp':
    				case 'pp-30-500-blp':
    					typereason = 'زیر پا گذاشتن سیاست زندگی‌نامهٔ زندگان'; // localized
    					break;
    				case 'pp-move-dispute':
    					typereason = 'مناقشه/جنگ بر سر عنوان/انتقال'; // localized
    					break;
    				case 'pp-move-vandalism':
    					typereason = 'خرابکاری از طریق انتقال صفحات'; // localized
    					break;
    				case 'pp-move-indef':
    					typereason = 'صفحهٔ پربازدید'; // localized
    					break;
    				case 'pp-create-offensive':
    					typereason = 'نام نامناسب'; // localized
    					break;
    				case 'pp-create-blp':
    					typereason = 'زندگی‌نامهٔ زندگان که به تازگی حذف شده'; // localized
    					break;
    				case 'pp-create-salt':
    					typereason = 'ایجادهای پی‌درپی'; // localized
    					break;
    				default:
    					typereason = '';
    					break;
    			}

    			var reason = typereason;
    			if (form.reason.value !== '') {
    				if (typereason !== '') {
    					reason += '\u00A0\u2013 ';  // U+00A0 NO-BREAK SPACE; U+2013 EN RULE
    				}
    				reason += form.reason.value;
    			}
    			if (reason !== '' && reason.charAt(reason.length - 1) !== '.') {
    				reason += '.';
    			}

    			var rppparams = {
    				reason: reason,
    				typename: typename,
    				category: form.category.value,
    				expiry: form.expiry.value
    			};

    			Morebits.simpleWindow.setButtonsEnabled(false);
    			Morebits.status.init(form);

    			var rppName = 'ویکی‌پدیا:درخواست محافظت صفحه'; // localized

    			// Updating data for the action completed event
    			Morebits.wiki.actionCompleted.redirect = rppName;
    			Morebits.wiki.actionCompleted.notice = 'درخواست کامل شد، درحال بازگشت به صفحه بحث'; // localized

    			var rppPage = new Morebits.wiki.page(rppName, 'درحال درخواست برای محافظت از صفحه'); // localized
    			rppPage.setFollowRedirect(true);
    			rppPage.setCallbackParameters(rppparams);
    			rppPage.load(Twinkle.protect.callbacks.fileRequest);
    			break;
    		default:
    			alert('twinkleprotect: نوع کنش ناشناخته است');
    			break;
    	}
    };

    Twinkle.protect.callbacks = {
    	taggingPageInitial: function(tagparams) {
    		if (tagparams.tag === 'noop') {
    			Morebits.status.info(' اعمال الگوی حفاظت', 'کاری برای انجام نیست'); // localized
    			return;
    		}

    		var protectedPage = new Morebits.wiki.page(mw.config.get('wgPageName'), 'برچسب زدن صفحه'); // localized
    		protectedPage.setCallbackParameters(tagparams);
    		protectedPage.load(Twinkle.protect.callbacks.taggingPage);
    	},
    	taggingPage: function(protectedPage) {
    		var params = protectedPage.getCallbackParameters();
    		var text = protectedPage.getPageText();
    		var tag, summary;

    		var oldtag_re = /\s*(?:<noinclude>)?\s*\{\{\s*(pp-[^{}]*?|protected|(?:t|v|s|p-|usertalk-v|usertalk-s|sb|move)protected(?:2)?|protected template|privacy protection)\s*?\}\}\s*(?:<\/noinclude>)?\s*/gi;
    		var re_result = oldtag_re.exec(text);
    		if (re_result) {
    			if (params.tag === 'none' || confirm('{{' + re_result[1] + '}} در صفحه یافت نشد. \nبرای حذف آن تأیید و برای نگه‌داشتن آن لغو را کلیک کنید.')) { // localized
    				text = text.replace(oldtag_re, '');
    			}
    		}

    		if (params.tag === 'none') {
    			summary = 'حذف الگوی حفاظت' + Twinkle.getPref('summaryAd'); // localized
    		} else {
    			tag = params.tag;
    			if (params.reason) {
    				tag += '|reason=' + params.reason;
    			}
    			if (params.small) {
    				tag += '|small=yes';
    			}

    			if (/^\s*#redirect/i.test(text)) { // redirect page
    				// Only tag if no {{rcat shell}} is found
    				if (!text.match(/{{(?:redr|این یک تغییرمسیر است|this is a redirect|r(?:edirect)?(?:.?cat.*)?[ _]?sh)/i)) {
    					text = text.replace(/#(تغییرمسیر|تغییر_مسیر|REDIRECT) ?(\[\[.*?\]\])(.*)/i, '#تغییرمسیر $1$2\n\n{{' + tag + '}}');
    				} else {
    					Morebits.status.info('پوستهٔ ردهٔ تغییر مسیر موجود است', 'کاری برای انجام وجود ندارد'); // localized
    					return;
    				}
    			} else if (params.noinclude) {
    				text = '<noinclude>{{' + tag + '}}</noinclude>' + text;
    			} else {
    				text = '{{' + tag + '}}\n' + text;
    			}
    			summary = 'افزودن {{' + params.tag + '}}' + Twinkle.getPref('summaryAd'); // localized
    		}

    		protectedPage.setEditSummary(summary);
    		protectedPage.setPageText(text);
    		protectedPage.setCreateOption('nocreate');
    		protectedPage.suppressProtectWarning(); // no need to let admins know they are editing through protection
    		protectedPage.save();
    	},

    	fileRequest: function(rppPage) {

    		var params = rppPage.getCallbackParameters();
    		var text = rppPage.getPageText();
    		var statusElement = rppPage.getStatusElement();

    		var rppRe = new RegExp('===\\s*(\\[\\[)?\\s*:?\\s*' + RegExp.escape(Morebits.pageNameNorm, true) + '\\s*(\\]\\])?\\s*===', 'm');
    		var tag = rppRe.exec(text);

    		var rppLink = document.createElement('a');
    		rppLink.setAttribute('href', mw.util.getUrl(rppPage.getPageName()));
    		rppLink.appendChild(document.createTextNode(rppPage.getPageName()));

    		if (tag) {
    			statusElement.error([ 'در حال حاضر درخواست حفاظتی برای این صفحه در ', rppLink, ' موجود است، ادامه نمی‌دهیم' ]); // localized
    			return;
    		}

    		var newtag = '=== [[:' + Morebits.pageNameNorm + ']] ===\n';
    		if (new RegExp('^' + RegExp.escape(newtag).replace(/\s+/g, '\\s*'), 'm').test(text)) {
    			statusElement.error([ 'در حال حاضر درخواست حفاظتی برای این صفحه در ', rppLink, ' موجود است، ادامه نمی‌دهیم' ]); // localized
    			return;
    		}
    		newtag += '* {{pagelinks|1=' + Morebits.pageNameNorm + '}}\n\n';

    		var words;
    		switch (params.expiry) {
    			case 'temporary':
    				words = ' موقت'; // localized
    				break;
    			case 'indefinite':
    				words = ' بی‌پایان'; // localized
    				break;
    			default:
    				words = '';
    				break;
    		}

    		words = params.typename + words;

    		newtag += "'''" + Morebits.string.toUpperCaseFirstChar(words) + (params.reason !== '' ? ":''' " +
    			Morebits.string.formatReasonText(params.reason) : ".'''") + ' ~~~~';

    		// If either protection type results in a increased status, then post it under increase
    		// else we post it under decrease
    		var increase = false;
    		var protInfo = Twinkle.protect.protectionPresetsInfo[params.category];

    		// function to compute protection weights (see comment at Twinkle.protect.protectionWeight)
    		var computeWeight = function(mainLevel, stabilizeLevel) {
    			var result = Twinkle.protect.protectionWeight[mainLevel || 'all'];
    			if (stabilizeLevel) {
    				if (result) {
    					if (stabilizeLevel.level === 'autoconfirmed') {
    						result += 2;
    					}
    				} else {
    					result = Twinkle.protect.protectionWeight['flaggedrevs_' + stabilizeLevel];
    				}
    			}
    			return result;
    		};

    		// compare the page's current protection weights with the protection we are requesting
    		var editWeight = computeWeight(Twinkle.protect.currentProtectionLevels.edit &&
    			Twinkle.protect.currentProtectionLevels.edit.level,
    		Twinkle.protect.currentProtectionLevels.stabilize &&
    			Twinkle.protect.currentProtectionLevels.stabilize.level);
    		if (computeWeight(protInfo.edit, protInfo.stabilize) > editWeight ||
    			computeWeight(protInfo.move) > computeWeight(Twinkle.protect.currentProtectionLevels.move &&
    			Twinkle.protect.currentProtectionLevels.move.level) ||
    			computeWeight(protInfo.create) > computeWeight(Twinkle.protect.currentProtectionLevels.create &&
    			Twinkle.protect.currentProtectionLevels.create.level)) {
    			increase = true;
    		}

    		var reg;
    		if (increase) {
    			reg = /(\n==\s*درخواست‌های خروج از محافظت\s*==)/; // localized
    		} else {
    			reg = /(\n==\s*درخواست ویرایش صفحه‌های محافظت‌شده\s*==)/; // localized
    		}

    		var originalTextLength = text.length;
    		text = text.replace(reg, '\n' + newtag + '\n$1');
    		if (text.length === originalTextLength) {
    			var linknode = document.createElement('a');
    			linknode.setAttribute('href', mw.util.getUrl('ویکی‌پدیا:توینکل/تعمیر')); // localized
    			linknode.appendChild(document.createTextNode('چگونگی تعمیر دمص'));
    			statusElement.error([ 'عنوانی مناسب در وپ:دمص یافت نشد. برای حل این مشکل ', linknode, ' را ببینید' ]); // localized
    			return;
    		}
    		statusElement.status('افزودن درخواست جدید...'); // localized
    		rppPage.setEditSummary('/* ' + Morebits.pageNameNorm + ' */ درخواست ' + params.typename + (params.typename === 'pending changes' ? ' برای [[:' : ' برای [[:') + // localized
    			Morebits.pageNameNorm + ']].' + Twinkle.getPref('summaryAd'));
    		rppPage.setPageText(text);
    		rppPage.setCreateOption('recreate');
    		rppPage.save();
    	}
    };
    })(jQuery);

    // </nowiki>

Retrieved from "https://en.faraghaib.ir/w/index.php?title=MediaWiki:Gadget-twinkleprotect-2020.js&oldid=466"