# MediaWiki:Gadget-twinkleblock-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($) {

    var api = new mw.Api(), relevantUserName;
    var menuFormattedNamespaces = $.extend({}, mw.config.get('wgFormattedNamespaces'));
    menuFormattedNamespaces[0] = '(مقاله)'; // localized

    /*
     ****************************************
     *** twinkleblock.js: Block module
     ****************************************
     * Mode of invocation:     Tab ("Block")
     * Active on:             Any page with relevant user name (userspace, contribs, etc.)
     */

    Twinkle.block = function twinkleblock() {
    	// should show on Contributions or Block pages, anywhere there's a relevant user
    	if (Morebits.userIsSysop && mw.config.get('wgRelevantUserName')) {
    		Twinkle.addPortletLink(Twinkle.block.callback, 'بستن', 'tw-block', 'قطع دسترسی یک کاربر'); // localized
    	}
    };

    Twinkle.block.callback = function twinkleblockCallback() {
    	if (mw.config.get('wgRelevantUserName') === mw.config.get('wgUserName') &&
    			!confirm('شما در حال قطع دسترسی خودتان هستید! آیا مطمئنید که می‌خواهید ادامه دهید؟')) { // localized
    		return;
    	}

    	Twinkle.block.currentBlockInfo = undefined;
    	Twinkle.block.field_block_options = {};
    	Twinkle.block.field_template_options = {};

    	var Window = new Morebits.simpleWindow(650, 530);
    	// need to be verbose about who we're blocking
    	Window.setTitle('قطع دسترسی یا افزودن الگوی قطع دسترسی برای ' + mw.config.get('wgRelevantUserName')); // localized
    	Window.setScriptName('توینکل'); // localized
    	// Window.addFooterLink('Block templates', 'Template:Uw-block/doc/Block_templates'); // localized [removed]
    	Window.addFooterLink('سیاست قطع دسترسی', 'وپ:بستن'); // localized
    	Window.addFooterLink('راهنمای توینکل', 'en:WP:TW/DOC#block'); // localized

    	var form = new Morebits.quickForm(Twinkle.block.callback.evaluate);
    	var actionfield = form.append({
    		type: 'field',
    		label: 'نوع عمل' // localized
    	});
    	actionfield.append({
    		type: 'checkbox',
    		name: 'actiontype',
    		event: Twinkle.block.callback.change_action,
    		list: [
    			{
    				label: 'قطع دسترسی کاربر', // localized
    				value: 'قطع دسترسی', // localized
    				tooltip: 'با استفاده از گزینه‌های ارائه شده، دسترسی کاربر را قطع کنید. اگر قطع دسترسی موردی انتخاب نشود، قطع دسترسی کلی خواهد بود.', // localized
    				checked: true
    			},
    			{
    				label: 'قطع دسترسی موردی', // localized
    				value: 'partial',
    				tooltip: 'انجام یا ثبت قطع دسترسی موردی', // localized
    				checked: Twinkle.getPref('defaultToPartialBlocks')
    			},
    			{
    				label: 'افزودن الگوی قطع دسترسی به صفحهٔ بحث کاربر', // localized
    				value: 'template',
    				tooltip: 'اگر مدیری که قطع دسترسی را انجام داده فراموش کرده که الگوی قطع دسترسی را در صفحهٔ بحث کاربر بگذارد، یا شما حسابی را قطع دسترسی کردید بدون آن که الگوی مذکور را در صفحهٔ بحث کاربر بگذارید، می‌توانید از این روش برای ثبت الگوی مناسب استفاده کنید.', // localized
    				checked: true
    			}
    		]
    	});

    	form.append({ type: 'field', label: 'تنظیم اولیه', name: 'field_preset' }); // localized
    	form.append({ type: 'field', label: 'گزینه‌های الگو', name: 'field_template_options' }); // localized
    	form.append({ type: 'field', label: 'گزینه‌های بستن', name: 'field_block_options' }); // localized

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

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

    	Twinkle.block.fetchUserInfo(function() {
    		// clean up preset data (defaults, etc.), done exactly once, must be before Twinkle.block.callback.change_action is called
    		Twinkle.block.transformBlockPresets();
    		if (Twinkle.block.currentBlockInfo) {
    			Window.addFooterLink('باز کردن کاربر', 'Special:Unblock/' + mw.config.get('wgRelevantUserName'), true); // localized
    		}

    		// init the controls after user and block info have been fetched
    		var evt = document.createEvent('Event');
    		evt.initEvent('change', true, true);
    		result.actiontype[0].dispatchEvent(evt);
    	});
    };

    Twinkle.block.fetchUserInfo = function twinkleblockFetchUserInfo(fn) {
    	api.get({
    		format: 'json',
    		action: 'query',
    		list: 'blocks|users|logevents',
    		letype: 'block',
    		lelimit: 1,
    		bkusers: mw.config.get('wgRelevantUserName'),
    		ususers: mw.config.get('wgRelevantUserName'),
    		letitle: 'User:' + mw.config.get('wgRelevantUserName')
    	})
    		.then(function(data) {
    			var blockinfo = data.query.blocks[0],
    				userinfo = data.query.users[0];

    			Twinkle.block.isRegistered = !!userinfo.userid;
    			relevantUserName = Twinkle.block.isRegistered ? 'کاربر:' + mw.config.get('wgRelevantUserName') : mw.config.get('wgRelevantUserName');

    			if (blockinfo) {
    			// handle frustrating system of inverted boolean values
    				blockinfo.disabletalk = blockinfo.allowusertalk === undefined;
    				blockinfo.hardblock = blockinfo.anononly === undefined;
    				Twinkle.block.currentBlockInfo = blockinfo;
    			}

    			Twinkle.block.hasBlockLog = !!data.query.logevents.length;
    			// Used later to check if block status changed while filling out the form
    			Twinkle.block.blockLogId = Twinkle.block.hasBlockLog ? data.query.logevents[0].logid : false;

    			if (typeof fn === 'function') {
    				return fn();
    			}
    		}, function(msg) {
    			Morebits.status.init($('div[name="currentblock"] span').last()[0]);
    			Morebits.status.warn('خطا در دریافت اطلاعات کاربر', msg); // localized
    		});
    };

    Twinkle.block.callback.saveFieldset = function twinkleblockCallbacksaveFieldset(fieldset) {
    	Twinkle.block[$(fieldset).prop('name')] = {};
    	$(fieldset).serializeArray().forEach(function(el) {
    		// namespaces and pages for partial blocks are overwritten
    		// here, but we're handling them elsewhere so that's fine
    		Twinkle.block[$(fieldset).prop('name')][el.name] = el.value;
    	});
    };

    Twinkle.block.callback.change_action = function twinkleblockCallbackChangeAction(e) {
    	var field_preset, field_template_options, field_block_options, $form = $(e.target.form);
    	// Make ifs shorter
    	var blockBox = $form.find('[name=actiontype][value=block]').is(':checked');
    	var templateBox = $form.find('[name=actiontype][value=template]').is(':checked');
    	var partial = $form.find('[name=actiontype][value=partial]');
    	var partialBox = partial.is(':checked');
    	var blockGroup = partialBox ? Twinkle.block.blockGroupsPartial : Twinkle.block.blockGroups;

    	partial.prop('disabled', !blockBox && !templateBox);

    	Twinkle.block.callback.saveFieldset($('[name=field_block_options]'));
    	Twinkle.block.callback.saveFieldset($('[name=field_template_options]'));

    	if (blockBox) {
    		field_preset = new Morebits.quickForm.element({ type: 'field', label: 'پیش‌تنظیمات', name: 'field_preset' });
    		field_preset.append({
    			type: 'select',
    			name: 'preset',
    			label: 'انتخاب یک تنظیم اولیه:', // localized
    			event: Twinkle.block.callback.change_preset,
    			list: Twinkle.block.callback.filtered_block_groups(blockGroup)
    		});

    		field_block_options = new Morebits.quickForm.element({ type: 'field', label: 'گزینه‌های قطع دسترسی', name: 'field_block_options' }); // localized
    		field_block_options.append({ type: 'div', name: 'hasblocklog', label: ' ' });
    		field_block_options.append({ type: 'div', name: 'currentblock', label: ' ' });
    		field_block_options.append({
    			type: 'select',
    			name: 'expiry_preset',
    			label: 'زمان سرآمدن:', // localized
    			event: Twinkle.block.callback.change_expiry,
    			list: [
    				{ label: 'سفارشی', value: 'custom', selected: true }, // localized
    				{ label: 'بی‌پایان', value: 'infinity' }, // localized
    				{ label: '۳ ساعت', value: '3 hours' }, // localized
    				{ label: '۱۲ ساعت', value: '12 hours' }, // localized
    				{ label: '۲۴ ساعت', value: '24 hours' }, // localized
    				{ label: '۳۱ ساعت', value: '31 hours' }, // localized
    				{ label: '۳۶ ساعت', value: '36 hours' }, // localized
    				{ label: '۴۸ ساعت', value: '48 hours' }, // localized
    				{ label: '۶۰ ساعت', value: '60 hours' }, // localized
    				{ label: '۷۲ ساعت', value: '72 hours' }, // localized
    				{ label: '۱ هفته', value: '1 week' }, // localized
    				{ label: '۲ هفته', value: '2 weeks' }, // localized
    				{ label: '۱ ماه', value: '1 month' }, // localized
    				{ label: '۳ ماه', value: '3 months' }, // localized
    				{ label: '۶ ماه', value: '6 months' }, // localized
    				{ label: '۱ سال', value: '1 year' }, // localized
    				{ label: '۲ سال', value: '2 years' }, // localized
    				{ label: '۳ سال', value: '3 years' } // localized
    			]
    		});
    		field_block_options.append({
    			type: 'input',
    			name: 'expiry',
    			label: 'زمان سرآمدن سفارشی', // localized
    			tooltip: 'می‌توانید یک زمان نسبی به انگلیسی وارد کنید (مثلاً 1 minute یا 19 days) یا این که یک زمان مشخص را به صورت yyyymmddhhmm با ارقام انگلسی وارد کنید (مثلاً 200602011405 می‌شود ساعت ۱۴:۰۵ روز ۱ فوریهٔ ۲۰۰۶)', // localizde
    			value: Twinkle.block.field_block_options.expiry || Twinkle.block.field_template_options.template_expiry
    		});

    		if (partialBox) { // Partial block
    			field_block_options.append({
    				type: 'select',
    				multiple: true,
    				name: 'pagerestrictions',
    				label: 'صفحه‌های مورد قطع دسترسی', // localized
    				value: '',
    				tooltip: 'حداکثر ۱۰ مورد.' // localized
    			});
    			var ns = field_block_options.append({
    				type: 'select',
    				multiple: true,
    				name: 'namespacerestrictions',
    				label: 'فضاهای نام مورد قطع دسترسی', // localized
    				value: '',
    				tooltip: 'جلوگیری از ویرایش این فضاهای نام.', // localized
    			});
    			$.each(menuFormattedNamespaces, function(number, name) {
    				// Ignore -1: Special; -2: Media; and 2300-2303: Gadget (talk) and Gadget definition (talk)
    				if (number >= 0 && number < 830) {
    					ns.append({ type: 'option', label: name, value: number });
    				}
    			});
    		}

    		var blockoptions = [
    			{
    				checked: Twinkle.block.field_block_options.nocreate,
    				label: 'جلوگیری از ایجاد حساب', // localized
    				name: 'nocreate',
    				value: '1'
    			},
    			{
    				checked: Twinkle.block.field_block_options.noemail,
    				label: 'جلوگیری از ارسال ایمیل', // localized
    				name: 'noemail',
    				value: '1'
    			},
    			{
    				checked: Twinkle.block.field_block_options.disabletalk,
    				label: 'جلوگیری از ویرایش صفحهٔ بحث در مدت قطع دسترسی', // localized
    				name: 'disabletalk',
    				value: '1',
    				tooltip: partialBox ? 'در صورت اعمال قطع دسترسی موردی، این گزینه باید خاموش باشد مگر اینکه شما بخواهید از ویرایش کاربر در فضای نام بحث کاربر نیز جلوگیری کنید' : '' // localized
    			}
    		];

    		if (Twinkle.block.isRegistered) {
    			blockoptions.push({
    				checked: Twinkle.block.field_block_options.autoblock,
    				label: 'بستن خودکار نشانی‌های‌آی‌پی', // localized
    				name: 'autoblock',
    				value: '1'
    			});
    		} else {
    			blockoptions.push({
    				checked: Twinkle.block.field_block_options.hardblock,
    				label: 'بستن حساب‌های ثبت‌نام کرده از همین نشانی آی‌پی', // localized
    				name: 'hardblock',
    				value: '1'
    			});
    		}

    		blockoptions.push({
    			checked: Twinkle.block.field_block_options.watchuser,
    			label: 'بستن صفحه‌های کاربر و بحث کاربر', // localized
    			name: 'watchuser',
    			value: '1'
    		});

    		field_block_options.append({
    			type: 'checkbox',
    			name: 'blockoptions',
    			list: blockoptions
    		});
    		field_block_options.append({
    			type: 'textarea',
    			label: 'دلیل (برای سیاههٔ قطع دسترسی):', // localized
    			name: 'reason',
    			tooltip: 'لطفاً جزئیات مفیدی را به پیام پیش‌فرض اضافه کنید.', // localized
    			value: Twinkle.block.field_block_options.reason
    		});

    		/*
    		field_block_options.append({
    			type: 'div',
    			name: 'filerlog_label',
    			label: 'See also:',
    			style: 'display:inline-block;font-style:normal !important',
    			tooltip: 'Insert a "see also" message to indicate whether the filter log or deleted contributions played a role in the decision to block.'
    		});
    		field_block_options.append({
    			type: 'checkbox',
    			name: 'filter_see_also',
    			event: Twinkle.block.callback.toggle_see_alsos,
    			style: 'display:inline-block; margin-right:5px',
    			list: [
    				{
    					label: 'Filter log',
    					checked: false,
    					value: 'filter log'
    				}
    			]
    		});
    		field_block_options.append({
    			type: 'checkbox',
    			name: 'deleted_see_also',
    			event: Twinkle.block.callback.toggle_see_alsos,
    			style: 'display:inline-block',
    			list: [
    				{
    					label: 'Deleted contribs',
    					checked: false,
    					value: 'deleted contribs'
    				}
    			]
    		});
    		*/ // localized [removed]

    		if (Twinkle.block.currentBlockInfo) {
    			field_block_options.append({ type: 'hidden', name: 'reblock', value: '1' });
    		}
    	}

    	if (templateBox) {
    		field_template_options = new Morebits.quickForm.element({ type: 'field', label: 'گزینه‌های الگو', name: 'field_template_options' }); // localized
    		field_template_options.append({
    			type: 'select',
    			name: 'template',
    			label: 'انتخاب الگوی صفحهٔ بحث:',
    			event: Twinkle.block.callback.change_template,
    			list: Twinkle.block.callback.filtered_block_groups(blockGroup, true),
    			value: Twinkle.block.field_template_options.template
    		});
    		field_template_options.append({
    			type: 'input',
    			name: 'article',
    			display: 'none',
    			label: 'صفحه برای پیونددهی',
    			value: '',
    			tooltip: 'صفحه‌ای که احتمالاً هدف اخلالگری بوده‌است را می توان در درون اعلان پیوند داد. برای این که به هیچ صفحه‌ای پیوند داده نشود، این جعبه را خالی بگذارید.'
    		});

    		// Only visible if partial and not blocking
    		field_template_options.append({
    			type: 'input',
    			name: 'area',
    			display: 'none',
    			label: 'محدودهٔ قطع دسترسی موردی',
    			value: '',
    			tooltip: 'توضیح اختیاری صفحات یا مکانهای نام کاربر از ویرایش مسدود شده است.' // localized
    		});

    		if (!blockBox) {
    			field_template_options.append({
    				type: 'input',
    				name: 'template_expiry',
    				display: 'none',
    				label: 'مدت زمان قطع دسترسی: ',
    				value: '',
    				tooltip: 'مدت زمان مسدود شدن برای نمونه ، ۲۴ ساعت ، ۲ هفته ، نامشخص و غیره ...' // localized
    			});
    		}
    		field_template_options.append({
    			type: 'input',
    			name: 'block_reason',
    			label: '«دسترسی شما قطع شده‌است زیرا ...» ',
    			display: 'none',
    			tooltip: 'یک دلیل اختیاری برای جایگزینی دلیل عمومی پیش فرض. فقط برای الگوهای بستن عمومی موجود است.', // localized
    			value: Twinkle.block.field_template_options.block_reason
    		});

    		if (blockBox) {
    			field_template_options.append({
    				type: 'checkbox',
    				name: 'blank_duration',
    				list: [
    					{
    						label: 'قرار ندادن تاریخ انقضا در الگو', // localized
    						checked: Twinkle.block.field_template_options.blank_duration,
    						tooltip: 'به جای اینکه مدت زمان را اضافه کنید، الگوی بستن را بخوانید "شما به طور موقت مسدود شده‌اید ..."' // localized
    					}
    				]
    			});
    		} else {
    			field_template_options.append({
    				type: 'checkbox',
    				list: [
    					{
    						label: 'جلوگیری از ویرایش صفحهٔ بحث', // localized
    						name: 'notalk',
    						checked: Twinkle.block.field_template_options.notalk,
    						tooltip: 'الگوی بحث را طوری تنظیم کن که به قطع دسترسی کاربر از ویرایش در بحث خودش نیز اشاره کند'
    					},
    					{
    						label: 'جلوگیری از ارسال ایمیل', // localized
    						name: 'noemail_template',
    						checked: Twinkle.block.field_template_options.noemail_template,
    						tooltip: 'اگر محدودهٔ قطع دسترسی موردی ارائه نشده‌است، الگوی قطع دسترسی را طوری تنظیم کن که به قطع دسترسی کاربر به ارسال ایمیل نیز اشاره کند'
    					},
    					{
    						label: 'جلوگیری از ایجاد حساب کاربری', // localized
    						name: 'nocreate_template',
    						checked: Twinkle.block.field_template_options.nocreate_template,
    						tooltip: 'اگر محدودهٔ قطع دسترسی موردی ارائه نشده‌است، الگوی قطع دسترسی را طوری تنظیم کن که غیرفعال شدن قابلیت ایجاد حساب برای کاربر نیز اشاره کند'
    					}
    				]
    			});
    		}

    		var $previewlink = $('<a id="twinkleblock-preivew-link">Preview</a>');
    		$previewlink.off('click').on('click', function() {
    			Twinkle.block.callback.preview($form[0]);
    		});
    		$previewlink.css({cursor: 'pointer'});
    		field_template_options.append({ type: 'div', id: 'blockpreview', label: [ $previewlink[0] ] });
    		field_template_options.append({ type: 'div', id: 'twinkleblock-previewbox', style: 'display: none' });
    	}

    	var oldfield;
    	if (field_preset) {
    		oldfield = $form.find('fieldset[name="field_preset"]')[0];
    		oldfield.parentNode.replaceChild(field_preset.render(), oldfield);
    	} else {
    		$form.find('fieldset[name="field_preset"]').hide();
    	}
    	if (field_block_options) {
    		oldfield = $form.find('fieldset[name="field_block_options"]')[0];
    		oldfield.parentNode.replaceChild(field_block_options.render(), oldfield);

    		$form.find('[name=pagerestrictions]').select2({
    			width: '100%',
    			placeholder: 'صفحات را برای بستن کاربر انتخاب کنید', // localized
    			language: {
    				errorLoading: function() {
    					return 'عبارت جستجوی ناقص یا نامعتبر';
    				}
    			},
    			maximumSelectionLength: 10, // Software limitation [[phab:T202776]]
    			minimumInputLength: 1, // prevent ajax call when empty
    			ajax: {
    				url: mw.util.wikiScript('api'),
    				dataType: 'json',
    				delay: 100,
    				data: function(params) {
    					var title = mw.Title.newFromText(params.term);
    					if (!title) {
    						return;
    					}
    					return {
    						'action': 'query',
    						'format': 'json',
    						'list': 'allpages',
    						'apfrom': title.title,
    						'apnamespace': title.namespace,
    						'aplimit': '10'
    					};
    				},
    				processResults: function(data) {
    					return {
    						results: data.query.allpages.map(function(page) {
    							var title = mw.Title.newFromText(page.title, page.ns).toText();
    							return {
    								id: title,
    								text: title
    							};
    						})
    					};
    				}
    			},
    			templateSelection: function(choice) {
    				return $('<a>').text(choice.text).attr({
    					href: mw.util.getUrl(choice.text),
    					target: '_blank'
    				});
    			}
    		});

    		$form.find('[name=namespacerestrictions]').select2({
    			width: '100%',
    			matcher: Morebits.select2.matchers.wordBeginning,
    			language: {
    				searching: Morebits.select2.queryInterceptor
    			},
    			templateResult: Morebits.select2.highlightSearchMatches,
    			placeholder: 'انتخاب فضای نام برای قطع دسترسی موردی کاربر'
    		});

    		mw.util.addCSS(
    			// prevent dropdown from appearing behind the dialog, just in case
    			'.select2-container { z-index: 10000; }' +
    			// Reduce padding
    			'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
    			// Adjust font size
    			'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
    			'.select2-container .selection .select2-selection__rendered { font-size: 13px; }' +
    			// Remove black border
    			'.select2-container--default.select2-container--focus .select2-selection--multiple { border: 1px solid #aaa; }' +
    			// Make the tiny cross larger
    			'.select2-selection__choice__remove { font-size: 130%; }'
    		);
    	} else {
    		$form.find('fieldset[name="field_block_options"]').hide();
    		// Clear select2 options
    		$form.find('[name=pagerestrictions]').val(null).trigger('change');
    		$form.find('[name=namespacerestrictions]').val(null).trigger('change');
    	}
    	if (field_template_options) {
    		oldfield = $form.find('fieldset[name="field_template_options"]')[0];
    		oldfield.parentNode.replaceChild(field_template_options.render(), oldfield);
    		e.target.form.root.previewer = new Morebits.wiki.preview($(e.target.form.root).find('#twinkleblock-previewbox').last()[0]);
    	} else {
    		$form.find('fieldset[name="field_template_options"]').hide();
    	}

    	if (Twinkle.block.hasBlockLog) {
    		var $blockloglink = $('<a target="_blank" href="' + mw.util.getUrl('ویژه:سیاهه‌ها', {action: 'view', page: mw.config.get('wgRelevantUserName'), type: 'block'}) + '">سیاهه بسته‌شدن</a>)');

    		Morebits.status.init($('div[name="hasblocklog"] span').last()[0]);
    		Morebits.status.warn('این کاربر در گذشته قطع دسترسی شده‌است', $blockloglink[0]);
    	}

    	if (Twinkle.block.currentBlockInfo) {
    		Morebits.status.init($('div[name="currentblock"] span').last()[0]);
    		// list=blocks without bkprops (as we do in fetchUerInfo)
    		// returns partial: '' if the user is partially blocked
    		var statusStr = relevantUserName + ' به‌صورت ' + (Twinkle.block.currentBlockInfo.partial === '' ? 'موردی' : 'کلی') + 'قطع دسترسی شد';
    		if (Twinkle.block.currentBlockInfo.expiry === 'infinity') {
    			statusStr += ' (بی‌پایان)';
    		} else if (new Morebits.date(Twinkle.block.currentBlockInfo.expiry).isValid()) {
    			statusStr += ' (منقضی در ' + new Morebits.date(Twinkle.block.currentBlockInfo.expiry).calendar('utc') + ')';
    		}
    		var infoStr = 'برای تغییر قطع دسترسی سوال کنید'; // localized
    		if (Twinkle.block.currentBlockInfo.partial === undefined && partialBox) {
    			infoStr += '، تبدیل به قطع دسترسی موردی';
    		} else if (Twinkle.block.currentBlockInfo.partial === '' && !partialBox) {
    			infoStr += '، تبدیل به قطع دسترسی کلی';
    		}
    		Morebits.status.warn(statusStr, infoStr);
    		Twinkle.block.callback.update_form(e, Twinkle.block.currentBlockInfo);
    	}
    	if (templateBox) {
    		// make sure all the fields are correct based on defaults
    		if (blockBox) {
    			Twinkle.block.callback.change_preset(e);
    		} else {
    			Twinkle.block.callback.change_template(e);
    		}
    	}
    };

    /*
     * Keep alphabetized by key name, Twinkle.block.blockGroups establishes
     *    the order they will appear in the interface
     *
     * Block preset format, all keys accept only 'true' (omit for false) except where noted:
     * <title of block template> : {
     *   autoblock: <autoblock any IP addresses used (for registered users only)>
     *   disabletalk: <disable user from editing their own talk page while blocked>
     *   expiry: <string - expiry timestamp, can include relative times like "5 months", "2 weeks" etc>
     *   forAnonOnly: <show block option in the interface only if the relevant user is an IP>
     *   forRegisteredOnly: <show block option in the interface only if the relevant user is registered>
     *   label: <string - label for the option of the dropdown in the interface (keep brief)>
     *   noemail: prevent the user from sending email through Special:Emailuser
     *   pageParam: <set if the associated block template accepts a page parameter>
     *   prependReason: <string - prepends the value of 'reason' to the end of the existing reason, namely for when revoking talk page access>
     *   nocreate: <block account creation from the user's IP (for anonymous users only)>
     *   nonstandard: <template does not conform to stewardship of WikiProject User Warnings and may not accept standard parameters>
     *   reason: <string - block rationale, as would appear in the block log,
     *            and the edit summary for when adding block template, unless 'summary' is set>
     *   reasonParam: <set if the associated block template accepts a reason parameter>
     *   sig: <string - set to ~~~~ if block template does not accept "true" as the value, or set null to omit sig param altogether>
     *   summary: <string - edit summary for when adding block template to user's talk page, if not set, 'reason' is used>
     *   suppressArticleInSummary: <set to suppress showing the article name in the edit summary, as with attack pages>
     *   templateName: <string - name of template to use (instead of key name), entry will be omitted from the Templates list.
     *                  (e.g. use another template but with different block options)>
     *   useInitialOptions: <when preset is chosen, only change given block options, leave others as they were>
     *
     * WARNING: 'anononly' and 'allowusertalk' are enabled by default.
     *   To disable, set 'hardblock' and 'disabletalk', respectively
     */
    Twinkle.block.blockPresetsInfo = {
    	'anonblock': {
    		expiry: '31 hours',
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{anonblock}}',
    		sig: '~~~~'
    	},
    	'anonblock - school': {
    		expiry: '36 hours',
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{anonblock}} <!-- بر پایه شواهد، احتمالاً مبتنی بر مدرسه است -->',
    		templateName: 'anonblock',
    		sig: '~~~~'
    	},
    	'blocked proxy': {
    		expiry: '1 year',
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		hardblock: true,
    		reason: '{{پروکسی باز}}', // localized
    		sig: null
    	},
    	'CheckUser block': {
    		expiry: '1 week',
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{قطع دسترسی بازرسی کاربر}}', // localized
    		sig: '~~~~'
    	},
    	'checkuserblock-account': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{بندایش بازرسی کاربر-حساب کاربری}}', // localized
    		sig: '~~~~'
    	},
    	'checkuserblock-wide': {
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{checkuserblock-wide}}',
    		sig: '~~~~'
    	},
    	'colocationwebhost': {
    		expiry: '1 year',
    		forAnonOnly: true,
    		nonstandard: true,
    		reason: '{{میزبانی‌وب‌سرور}}', // localized
    		sig: null
    	},
    	'oversightblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{OversightBlock}}',
    		sig: '~~~~'
    	},
    	'school block': {
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{school block}}',
    		sig: '~~~~'
    	},
    	'spamblacklistblock': {
    		forAnonOnly: true,
    		expiry: '1 month',
    		disabletalk: true,
    		nocreate: true,
    		reason: '{{spamblacklistblock}} <!-- editor only attempts to add blacklisted links, see [[Special:Log/spamblacklist]] -->'
    	},
    	// Placeholder for when we add support for rangeblocks
    	// 'rangeblock' : {
    	//   reason: '{{rangeblock}}',
    	//   nocreate: true,
    	//   nonstandard: true,
    	//   forAnonOnly: true,
    	//   sig: '~~~~'
    	// },
    	'tor': {
    		expiry: '1 year',
    		forAnonOnly: true,
    		nonstandard: true,
    		reason: '{{Tor}}',
    		sig: null
    	},
    	'webhostblock': {
    		expiry: '1 year',
    		forAnonOnly: true,
    		nonstandard: true,
    		reason: '{{میزبان وب بسته‌شده}}', // localized
    		sig: null
    	},
    	// uw-prefixed
    	'uw-3block': {
    		autoblock: true,
    		expiry: '24 hours',
    		nocreate: true,
    		pageParam: true,
    		reason: 'نقض[[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]]', // localized
    		summary: 'برای نقض [[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]] شما از ویرایش منع شده‌اید' // localized
    	},
    	'uw-ablock': {
    		autoblock: true,
    		expiry: '31 hours',
    		forAnonOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reasonParam: true,
    		summary: 'آدرس IP شما از ویرایش منع شده است', // localized
    		suppressArticleInSummary: true
    	},
    	'uw-adblock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: 'استفاده از ویکی‌پدیا به عنوان [[ویکی‌پدیا:هرزنامه|هرزنامه]] یا [[ویکی‌پدیا:ویکی‌پدیا چه چیزی نیست|تبلیغات]] ', // localized
    		summary: 'شما به دلیل [[ویکی‌پدیا:ویکی‌پدیا چه چیزی نیست|ویکی‌پدیا چه چیزی نیست]] از ویرایش منع شده‌اید' // localized
    	},
    	'uw-aeblock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '[[WP:Arbitration enforcement|Arbitration enforcement]]',
    		reasonParam: true,
    		summary: 'شما به دلیل نقض [[WP:Arbitration|تصمیم داوری]] از ویرایش منع شده اید' // localized
    	},
    	'uw-bioblock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: 'نقض سیایت شرح حال [[ویکی‌پدیا:زندگی‌نامه زندگان|زندگی‌نامه زندگان]] ', // localized
    		summary: 'دسترسی ویرایش شما به‌دلیل نقض [[ویکی‌پدیا:زندگی‌نامه زندگان|سیاست زندگی‌نامهٔ زندگان]] قطع شده‌است'
    	},
    	'uw-block': {
    		autoblock: true,
    		expiry: '24 hours',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reasonParam: true,
    		summary: 'شما از ویرایش منع شده‌اید', // localized
    		suppressArticleInSummary: true
    	},
    	'uw-blockindef': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reasonParam: true,
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید', // localized
    		suppressArticleInSummary: true
    	},
    	'uw-blocknotalk': {
    		disabletalk: true,
    		pageParam: true,
    		reasonParam: true,
    		summary: 'شما از ویرایش منع شده‌اید و دسترسی به صفحه بحث کاربر غیرفعال شده است', // localized
    		suppressArticleInSummary: true
    	},
    	'uw-botblock': {
    		forRegisteredOnly: true,
    		pageParam: true,
    		reason: 'اجرای اسکریپت [[ویکی‌پدیا:ربات|ربات]] بدون [[ویکی‌پدیا:سیاست ربات‌رانی/درخواست مجوز|مجوز]]', // localized
    		summary: 'دسترسی ویرایشی شما قطع شده‌است. چرا که به‌نظر می‌رسد در حال راندن یک  [[ویکی‌پدیا:ربات|ربات]] بدون کسب [[ویکی‌پدیا:سیاست ربات‌رانی/درخواست مجوز|مجوز]] هستید' // localized
    	},
    	'uw-botublock': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{Uw-botublock}} <!-- نام کاربری نمایندهٔ ربات است، قطع دسترسی نرم -->',
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما نشان می دهد که این یک حساب [[ویکی‌پدیا:ربات|ربات]] است ، که در حال حاضر تأیید نشده است.' // localized
    	},
    	'uw-causeblock': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{Uw-causeblock}} <!-- نام کاربری نمایندهٔ یک سازمان ناسودبر است، قطع دسترسی نرم -->',
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما این تصور را ایجاد می‌کند که این حساب نماینده یک گروه، سازمان یا وب سایت است' // localized
    	},
    	'uw-compblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: 'امنیت حساب کاربری', // localized
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا اعتقاد بر این است که [[ویکی‌پدیا:امنیت حساب کاربری|امنیت حساب شما]] به خطر افتاده‌است.' // localized
    	},
    	'uw-copyrightblock': {
    		autoblock: true,
    		expiry: '24 hours',
    		nocreate: true,
    		pageParam: true,
    		reason: '[[وپ:حق تکثیر|نقض حق تکثیر]]',
    		summary: 'دسترسی ویرایشی شما به دلیل نقض مداوم [[وپ:حت|حق تکثیر]] قطع شده‌است' // localized
    	},
    	'uw-dblock': {
    		autoblock: true,
    		nocreate: true,
    		reason: 'حذف مدام محتوا', // localized
    		pageParam: true,
    		summary: 'به دلیل [[ویکی‌پدیا:خرابکاری|خرابکاری]] از ویرایش منع شده‌اید' // localized
    	},
    	'uw-disruptblock': {
    		autoblock: true,
    		nocreate: true,
    		reason: '[[ویکی‌پدیا:ویرایش اخلالگرانه|ویرایش اخلالگرانه]]', // localized
    		summary: 'به دلیل [[ویکی‌پدیا:ویرایش اخلالگرانه|ویرایش اخلالگرانه]] از ویرایش منع شده‌اید' // localized
    	},
    	'uw-efblock': {
    		autoblock: true,
    		nocreate: true,
    		reason: 'راه‌اندازی عمدی [[ویکی‌پدیا:پالایه ویرایش|پالایهٔ ویرایش]]', // localized
    		summary: 'شما به دلیل ویرایش‌های مخرب که مرتباً باعث [[ویکی‌پدیا:پالایه ویرایش|پالایه ویرایش]] شده‌اند، از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-ewblock': {
    		autoblock: true,
    		expiry: '24 hours',
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]]', // localized
    		summary: 'برای جلوگیری از [[ویکی‌پدیا:ویرایش اخلالگرانه|اختلال]] بیشتر ناشی از درگیری شما در [[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]]، از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-hblock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:حمله شخصی ممنوع|حملهٔ شخصی]] یا [[ویکی‌پدیا:آزار و اذیت|آزار و اذیت]]', // localized
    		summary: 'شما به دلیل [[ویکی‌پدیا:آزار و اذیت|آزار و اذیت]] سایر کاربران از ویرایش منع شده‌اید.'
    	},
    	'uw-ipevadeblock': {
    		forAnonOnly: true,
    		nocreate: true,
    		reason: '[[ویکی‌پدیا:قطع دسترسی|قطع دسترسی]]', // localized
    		summary: 'آدرس آی‌پی شما به دلیل [[ویکی‌پدیا:قطع دسترسی|قطع دسترسی]] از ویرایش منع شده‌است.' // localized
    	},
    	'uw-lblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		nocreate: true,
    		reason: '[[ویکی‌پدیا:تهدید قانونی ممنوع|تهدید قانونی]]', // localized
    		summary: 'شما به دلیل [[ویکی‌پدیا:تهدید قانونی ممنوع|تهدید قانونی ممنوع]] از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-nothereblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		nocreate: true,
    		reason: 'روشن است که [[ویکی‌پدیا:ما برای ساختن دانشنامه اینجا هستیم|برای ساختن دانشنامه اینجا نیستید.]]', // localized
    		forRegisteredOnly: true,
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا به نظر می‌رسد که شما برای [[ویکی‌پدیا:ما برای ساختن دانشنامه اینجا هستیم|ساختن دانشنامه]] اینجا نیستید' // localized
    	},
    	'uw-npblock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: 'ایجاد مزخرفات ثبت اختراع یا سایر [[ویکی‌پدیا:بی‌معنی|صفحات نامناسب]]', // localized
    		summary: 'به دلیل ایجاد صفحات [[ویکی‌پدیا:بی‌معنی|بی‌معنی]] از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-pablock': {
    		autoblock: true,
    		expiry: '31 hours',
    		nocreate: true,
    		reason: '[[ویکی‌پدیا:حمله شخصی ممنوع|]] یا [[ویکی‌پدیا:آزار و اذیت|]]', // localized
    		summary: 'شما به دلیل انجام [[ویکی‌پدیا:حمله شخصی ممنوع|حملات شخصی]] به سایر کاربران از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-sblock': {
    		autoblock: true,
    		nocreate: true,
    		reason: 'استفاده از ویکی‌پدیا به عنوان [[ویکی‌پدیا:هرزنامه|هرزنامه]]', // localized
    		summary: 'به دلیل استفاده از ویکی‌پدیا برای انتشار [[ویکی‌پدیا:هرزنامه|هرزنامه]] از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-soablock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:هرزنامه]] / [[ویکی‌پدیا:ویکی‌پدیا چه چیزی نیست]]-تنها حساب', // localized
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا حساب شما فقط برای ایجاد [[ویکی‌پدیا:هرزنامه|هرزنامه]] استفاده می‌شود.' // localized
    	},
    	'uw-socialmediablock': {
    		autoblock: true,
    		nocreate: true,
    		pageParam: true,
    		reason: 'استفاده از ویکی‌پدیا به عنوان [[ویکی‌پدیا:ویکی‌پدیا چه چیزی نیست|یک وبلاگ، میزبان وب، سایت یا شبکه‌های اجتماعی]]', // localized
    		summary: 'شما به دلیل استفاده از صفحات کاربر و / یا مقاله به عنوان [[ویکی‌پدیا:ویکی‌پدیا چه چیزی نیست|وبلاگ، میزبان وب، سایت یا شبکه‌های اجتماعی]] از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-sockblock': {
    		autoblock: true,
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: 'سوءاستفاده از [[ویکی‌پدیا:حساب زاپاس|چند حساب کاربری]]', // localized
    		summary: 'شما به دلیل سوء استفاده از [[ویکی‌پدیا:حساب زاپاس|چند حساب کاربری]] ویرایش منع شده‌اید ' // localized
    	},
    	'uw-softerblock': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{Uw-softerblock}} <!-- نام کاربری تبلیغاتی، قطع دسترسی نرم -->',
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما این تصور را ایجاد می‌کند که این حساب نماینده یک گروه، سازمان یا وب سایت است' // localized
    	},
    	'uw-spamublock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: '{{Uw-spamublock}} <!-- نام کاربری تبلیغاتی، ویرایش‌های تبلیغاتی -->',
    		summary: 'شما به‌طور نامحدود از ویرایش منع شده‌اید زیرا حساب شما فقط برای [[ویکی‌پدیا:هرزنامه|هرزنامه یا تبلیغات]] استفاده می‌شود و [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما نقض خط مشی نام کاربری است.' // localized
    	},
    	'uw-spoablock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: '[[ویکی‌پدیا:حساب زاپاس|حساب زاپاس]]', // localized
    		summary: 'این حساب به عنوان یک [[ویکی‌پدیا:حساب زاپاس|حساب زاپاس]] ایجاد شده و براساس نقض خط مشی ویکی پد مسدود شده است.' // localized
    	},
    	'uw-talkrevoked': {
    		disabletalk: true,
    		reason: 'لغو دسترسی به صفحه بحث: استفاده نامناسب از صفحه بحث کاربر در حالی که مسدود شده‌است.', // localized
    		prependReason: true,
    		summary: 'دسترسی به صفحه گفتگوی کاربر غیرفعال شده‌است', // localized
    		useInitialOptions: true
    	},
    	'uw-ublock': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{Uw-ublock}} <!-- نقض سیاست نام کاربر، قطع دسترسی نرم -->',
    		reasonParam: true,
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] ناقض قوانین است.' // localized
    	},
    	'uw-ublock-double': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{Uw-ublock-double}} <!-- Username closely resembles another user, soft block -->',
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما بیش از حد به نام کاربری کاربر ویکی‌پدیا دیگر شباهت دارد.' // localized
    	},
    	'uw-ucblock': {
    		autoblock: true,
    		expiry: '31 hours',
    		nocreate: true,
    		pageParam: true,
    		reason: ' [[راهنما:مقدمه‌ای بر ارجاع/۱|افزودن محتوای بدون منبع]]', // localized
    		summary: 'به دلیل افزودن مداوم از [[راهنما:مقدمه‌ای بر ارجاع/۱|محتوای بدون منبع]]، شما از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-uhblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: '{{Uw-uhblock}} <!-- نقض سیاست نام کاربر، قطع دسترسی سخت -->',
    		reasonParam: true,
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما نقض آشکار خط مشی نام کاربری است.' // localized
    	},
    	'uw-ublock-wellknown': {
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		reason: '{{بستن نام واقعی}} <!-- Username represents a well-known person, soft block -->',
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما با نام یک فرد شناخته شده زنده مطابقت دارد.' // localized
    	},
    	'uw-uhblock-double': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		reason: '{{Uw-ublock-double}} <!-- Username closely resembles another user, hard block -->',
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا به نظر می رسد [[ویکی‌پدیا:سیاست نام کاربری|نام کاربری]] شما نام یک کاربر دیگر ویکی پدیا را جعل می‌کند' // localized
    	},
    	'uw-upeblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:فاش‌سازی مشارکت در برابر دستمزد]] in violation of the WMF [[WP:TOU|Terms of Use]]',
    		summary: 'شما به طور نامحدود به دلیل [[ویکی‌پدیا:فاش‌سازی مشارکت در برابر دستمزد|فاش‌سازی مشارکت در برابر دستمزد]] از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-vaublock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '{{Uw-vaublock}} <!-- نقض سیاست نام کاربر، حساب ایجادشده تنها برای خرابکاری -->',
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا [[ویکی‌پدیا:حساب ساخته‌شده برای خرابکاری|حساب شما]] برای خرابکاری ایجاد شده‌است و ناقض [[ویکی‌پدیا:سیاست نام کاربری|سیاست نام کاربری]] است.' // localized
    	},
    	'uw-vblock': {
    		autoblock: true,
    		expiry: '31 hours',
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:خرابکاری|خرابکاری]]', // localized
    		summary: 'برای جلوگیری از بیشتر [[ویکی‌پدیا:خرابکاری|خرابکاری]] شما از ویرایش منع شده‌اید.' // localized
    	},
    	'uw-voablock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: true,
    		reason: '[[ویکی‌پدیا:حساب ساخته‌شده برای خرابکاری|حساب ساخته‌شده برای خرابکاری]]', // localized
    		summary: 'شما به طور نامحدود از ویرایش منع شده‌اید زیرا  حساب شما تنها برای [[ویکی‌پدیا:حساب ساخته‌شده برای خرابکاری|خرابکاری]] استفاده می‌شود.' // localized
    	},
    	'zombie proxy': {
    		expiry: '1 month',
    		forAnonOnly: true,
    		nocreate: true,
    		nonstandard: true,
    		reason: '{{زامبی پراکسی}}', // localized
    		sig: null
    	},

    	// Begin partial block templates, accessed in Twinkle.block.blockGroupsPartial
    	'uw-acpblock': {
    		autoblock: true,
    		expiry: '48 hours',
    		nocreate: true,
    		pageParam: false,
    		reasonParam: true,
    		reason: 'سوءاستفاده از [[ویکی‌پدیا:حساب زاپاس|حساب زاپاس]]', // localized
    		summary: 'به دلیل سوء استفاده از [[ویکی‌پدیا:حساب زاپاس|چندین حساب]] از [[ویکی‌پدیا:قطع دسترسی موردی|ایجاد حساب کاربری]] منع شده‌اید.' // localized
    	},
    	'uw-acpblockindef': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: true,
    		pageParam: false,
    		reasonParam: true,
    		reason: 'سوء استفاده از [[ویکی‌پدیا:حساب زاپاس|حساب زاپاس]]', // localized
    		summary: 'به دلیل سوء استفاده از [[ویکی‌پدیا:حساب زاپاس|چندین حساب]] از [[ویکی‌پدیا:قطع دسترسی موردی|ایجاد حساب کاربری]] منع شده‌اید.' // localized
    	},
    	'uw-aepblock': {
    		autoblock: true,
    		nocreate: false,
    		pageParam: false,
    		reason: '[[WP:Arbitration enforcement|Arbitration enforcement]]',
    		reasonParam: true,
    		summary: 'به دلیل [[WP:Arbitration|نقض تصمیم داوری]] از ویرایش [[ویکی‌پدیا:قطع دسترسی موردی|منع]] شده اید.' // localized
    	},
    	'uw-epblock': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: false,
    		noemail: true,
    		pageParam: false,
    		reasonParam: true,
    		reason: '[[ویکی‌پدیا:آزار و اذیت]] ایمیلی', // localized
    		summary: 'شما از ارسال ایمیل به ویرایشگران دیگر به دلیل [[ویکی‌پدیا:آزار و اذیت|آزار و اذیت]] [[ویکی‌پدیا:قطع دسترسی موردی|منع]] شده‌اید' // localized
    	},
    	'uw-ewpblock': {
    		autoblock: true,
    		expiry: '24 hours',
    		nocreate: false,
    		pageParam: false,
    		reasonParam: true,
    		reason: '[[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]]', // localized
    		summary: 'شما از ویرایش مناطق خاصی از دانشنامه [[ویکی‌پدیا:قطع دسترسی موردی|منع]] شده‌اید تا از [[ویکی‌پدیا:ویرایش اخلالگرانه|اختلال]] بیشتر ناشی از [[ویکی‌پدیا:جنگ ویرایشی|جنگ ویرایشی]] جلوگیری شود.' // localized
    	},
    	'uw-pblock': {
    		autoblock: true,
    		expiry: '24 hours',
    		nocreate: false,
    		pageParam: false,
    		reasonParam: true,
    		summary: 'شما از ویرایش بخش‌هایی از دانشنامه [[ویکی‌پدیا:قطع دسترسی مورد|منع]] شده‌اید.' // localized
    	},
    	'uw-pblockindef': {
    		autoblock: true,
    		expiry: 'infinity',
    		forRegisteredOnly: true,
    		nocreate: false,
    		pageParam: false,
    		reasonParam: true,
    		summary: 'شما از ویرایش بخش‌هایی از دانشنامه [[ویکی‌پدیا:قطع دسترسی مورد|منع]] شده‌اید.' // localized
    	}
    };

    Twinkle.block.transformBlockPresets = function twinkleblockTransformBlockPresets() {
    	// supply sensible defaults
    	$.each(Twinkle.block.blockPresetsInfo, function(preset, settings) {
    		settings.summary = settings.summary || settings.reason;
    		settings.sig = settings.sig !== undefined ? settings.sig : 'yes';
    		// despite this it's preferred that you use 'infinity' as the value for expiry
    		settings.indefinite = settings.indefinite || settings.expiry === 'infinity' || settings.expiry === 'infinite' || settings.expiry === 'indefinite' || settings.expiry === 'never';

    		if (!Twinkle.block.isRegistered && settings.indefinite) {
    			settings.expiry = '31 hours';
    		} else {
    			settings.expiry = settings.expiry || '31 hours';
    		}

    		Twinkle.block.blockPresetsInfo[preset] = settings;
    	});
    };

    // These are the groups of presets and defines the order in which they appear. For each list item:
    //   label: <string, the description that will be visible in the dropdown>
    //   value: <string, the key of a preset in blockPresetsInfo>
    Twinkle.block.blockGroups = [
    	{
    		label: 'دلایل معمول برای بستن',
    		list: [
    			{ label: 'ناشناس', value: 'anonblock' },
    			{ label: 'ناشناس - احتمالاً مدرسه', value: 'anonblock - school' },
    			{ label: 'بستن مدرسه', value: 'school block' },
    			{ label: 'بستن عمومی (دلیل سفارشی)', value: 'uw-block' }, // ends up being default for registered users
    			{ label: 'بستن عمومی (دلیل سفارشی) - آی‌پی', value: 'uw-ablock', selected: true }, // set only when blocking IP
    			{ label: 'بستن عمومی (دلیل سفارشی) - بی‌پایان', value: 'uw-blockindef' },
    			{ label: 'ویرایش اخلالگرانه', value: 'uw-disruptblock' },
    			{ label: 'استفادهٔ نادرست از صفحهٔ بحث کاربری در زمان بسته‌بودن', value: 'uw-talkrevoked' },
    			{ label: 'برای کمک به دانشنامه اینجا نیست', value: 'uw-nothereblock' },
    			{ label: 'محتوای بدون منبع', value: 'uw-ucblock' },
    			{ label: 'خرابکاری', value: 'uw-vblock' },
    			{ label: 'حساب ایجادشده تنها برای خرابکاری', value: 'uw-voablock' }
    		]
    	},
    	{
    		label: 'دلایل گسترده',
    		list: [
    			{ label: 'تبلیغات', value: 'uw-adblock' },
    			{ label: 'حکم هیئت', value: 'uw-aeblock' },
    			{ label: 'دور زدن قطع دسترسی - آی‌پی', value: 'uw-ipevadeblock' },
    			{ label: 'نقض سیاست زندگی‌نامه زندگان', value: 'uw-bioblock' },
    			{ label: 'نقض حق تکثیر', value: 'uw-copyrightblock' },
    			{ label: 'ایجاد صفحه‌های نامفهوم', value: 'uw-npblock' },
    			{ label: 'مرتبط با پالایهٔ ویرایش', value: 'uw-efblock' },
    			{ label: 'جنگ ویرایشی', value: 'uw-ewblock' },
    			{ label: 'بستن عمومی و گرفتن دسترسی صفحهٔ بحث', value: 'uw-blocknotalk' },
    			{ label: 'آزار و اذیت', value: 'uw-hblock' },
    			{ label: 'تهدید قانونی', value: 'uw-lblock' },
    			{ label: 'حملهٔ شخصی یا آزار و اذیت', value: 'uw-pablock' },
    			{ label: 'حساب به خطر افتاده', value: 'uw-compblock' },
    			{ label: 'حذف محتوا، خالی‌کردن', value: 'uw-dblock' },
    			{ label: 'زاپاس‌بازی (اصلی)', value: 'uw-sockblock' },
    			{ label: 'زاپاس‌بازی (زاپاس)', value: 'uw-spoablock' },
    			{ label: 'استفاده از ویکی‌پدیا مانند شبکه‌های اجتماعی', value: 'uw-socialmediablock' },
    			{ label: 'هرزنگاری', value: 'uw-sblock' },
    			{ label: 'حساب ایجادشده برای هرزنگاری/تبلیغات', value: 'uw-soablock' },
    			{ label: 'ربات بدون مجوز', value: 'uw-botblock' },
    			{ label: 'ویرایش دستمزدی فاش‌نشده', value: 'uw-upeblock' },
    			{ label: 'نقض قاعدهٔ سه‌برگردان', value: 'uw-3block' }
    		]
    	},
    	{
    		label: 'نقض سیاست نام کاربری',
    		list: [
    			{ label: 'نام کاربری ربات', value: 'uw-botublock' },
    			{ label: 'نام کاربری تبلیغاتی، بستن نرم', value: 'uw-spamublock' },
    			{ label: 'نام کاربری تبلیغاتی، بستن نرم', value: 'uw-softerblock' },
    			{ label: 'نام کاربری مشابه، بستن نرم', value: 'uw-ublock-double' },
    			{ label: 'نقض سیاست نام کاربری، بستن نرم', value: 'uw-ublock' },
    			{ label: 'نقض سیاست نام کاربری، بستن سخت', value: 'uw-uhblock' },
    			{ label: 'جعل هویت نام کاربری، بستن سخت', value: 'uw-uhblock-double' },
    			{ label: 'نام کاربری نمایندهٔ شخص شناخته‌شده است، بستن نرم', value: 'uw-ublock-wellknown' },
    			{ label: 'نام کاربری نمایندهٔ سازمان ناسودبر است، بستن نرم', value: 'uw-causeblock' },
    			{ label: 'نقض سیاست نام کاربری، حساب ایجادشده برای خرابکاری', value: 'uw-vaublock' }
    		]
    	},
    	{
    		label: 'دلایل آماده',
    		list: [
    			{ label: 'پروکسی باز', value: 'blocked proxy' },
    			{ label: 'بستن بازرسی کاربر', value: 'CheckUser block', disabled: !Morebits.userIsInGroup('checkuser') },
    			{ label: 'بستن بازرسی کاربر-حساب', value: 'checkuserblock-account', disabled: !Morebits.userIsInGroup('checkuser') },
    			{ label: 'بستن بازرسی کاربر-کلی', value: 'checkuserblock-wide', disabled: !Morebits.userIsInGroup('checkuser') },
    			{ label: 'میزبانی‌وب‌سرور', value: 'colocationwebhost' },
    			{ label: 'بستن پنهان‌گر', value: 'oversightblock', disabled: !Morebits.userIsInGroup('oversight') },
    			// { label: 'rangeblock', value: 'rangeblock' }, // placeholder for when we add support for rangeblocks
    			{ label: 'بستن نام کاربری تبلیغاتی', value: 'spamblacklistblock' },
    			{ label: 'تور', value: 'tor' },
    			{ label: 'بستن میزبانی وب', value: 'webhostblock' },
    			{ label: 'زامبی پراکسی', value: 'zombie proxy' }
    		]
    	}
    ];

    Twinkle.block.blockGroupsPartial = [
    	{
    		label: 'دلایل معمول برای قطع دسترسی موردی',
    		list: [
    			{ label: 'بستن موردی عمومی (دلیل سفارشی)', value: 'uw-pblock', selected: true },
    			{ label: 'بستن موردی عمومی (دلیل سفارشی) - بی‌پایان', value: 'uw-pblockindef' },
    			{ label: 'جنگ ویرایشی', value: 'uw-ewpblock' }
    		]
    	},
    	{
    		label: 'دلایل قابل تعمیم قطع دسترسی موردی',
    		list: [
    			{ label: 'حکم هیئت نظارت', value: 'uw-aepblock' },
    			{ label: 'آزار و اذیت با ایمیل', value: 'uw-epblock' },
    			{ label: 'سوءاستفاده از چند حساب', value: 'uw-acpblock' },
    			{ label: 'سوءاستفاده از چند حساب - بی‌پایان', value: 'uw-acpblockindef' }
    		]
    	}
    ];

    Twinkle.block.callback.filtered_block_groups = function twinkleblockCallbackFilteredBlockGroups(group, show_template) {
    	return $.map(group, function(blockGroup) {
    		var list = $.map(blockGroup.list, function(blockPreset) {
    			// only show uw-talkrevoked if reblocking
    			if (!Twinkle.block.currentBlockInfo && blockPreset.value === 'uw-talkrevoked') {
    				return;
    			}

    			var blockSettings = Twinkle.block.blockPresetsInfo[blockPreset.value];
    			var registrationRestrict = blockSettings.forRegisteredOnly ? Twinkle.block.isRegistered : blockSettings.forAnonOnly ? !Twinkle.block.isRegistered : true;
    			if (!(blockSettings.templateName && show_template) && registrationRestrict) {
    				var templateName = blockSettings.templateName || blockPreset.value;
    				return {
    					label: (show_template ? '{{' + templateName + '}}: ' : '') + blockPreset.label,
    					value: blockPreset.value,
    					data: [{
    						name: 'template-name',
    						value: templateName
    					}],
    					selected: !!blockPreset.selected,
    					disabled: !!blockPreset.disabled
    				};
    			}
    		});
    		if (list.length) {
    			return {
    				label: blockGroup.label,
    				list: list
    			};
    		}
    	});
    };

    Twinkle.block.callback.change_preset = function twinkleblockCallbackChangePreset(e) {
    	var key = e.target.form.preset.value;
    	if (!key) {
    		return;
    	}

    	e.target.form.template.value = Twinkle.block.blockPresetsInfo[key].templateName || key;
    	Twinkle.block.callback.update_form(e, Twinkle.block.blockPresetsInfo[key]);
    	Twinkle.block.callback.change_template(e);
    };

    Twinkle.block.callback.change_expiry = function twinkleblockCallbackChangeExpiry(e) {
    	var expiry = e.target.form.expiry;
    	if (e.target.value === 'custom') {
    		Morebits.quickForm.setElementVisibility(expiry.parentNode, true);
    	} else {
    		Morebits.quickForm.setElementVisibility(expiry.parentNode, false);
    		expiry.value = e.target.value;
    	}
    };

    Twinkle.block.seeAlsos = [];
    Twinkle.block.callback.toggle_see_alsos = function twinkleblockCallbackToggleSeeAlso() {
    	var reason = this.form.reason.value.replace(
    		new RegExp('( <!--|;) ' + 'همچنین ببینید: ' + Twinkle.block.seeAlsos.join(' و ') + '( -->)?'), ''
    	);

    	Twinkle.block.seeAlsos = Twinkle.block.seeAlsos.filter(function(el) {
    		return el !== this.value;
    	}.bind(this));

    	if (this.checked) {
    		Twinkle.block.seeAlsos.push(this.value);
    	}
    	var seeAlsoMessage = Twinkle.block.seeAlsos.join(' and ');

    	if (!Twinkle.block.seeAlsos.length) {
    		this.form.reason.value = reason;
    	} else if (reason.indexOf('{{') !== -1) {
    		this.form.reason.value = reason + ' <!-- همچنین ببینید ' + seeAlsoMessage + ' -->';
    	} else {
    		this.form.reason.value = reason + '؛ همچنین ببینید ' + seeAlsoMessage;
    	}
    };

    Twinkle.block.callback.update_form = function twinkleblockCallbackUpdateForm(e, data) {
    	var form = e.target.form, expiry = data.expiry;

    	// don't override original expiry if useInitialOptions is set
    	if (!data.useInitialOptions) {
    		if (Date.parse(expiry)) {
    			expiry = new Date(expiry).toGMTString();
    			form.expiry_preset.value = 'custom';
    		} else {
    			form.expiry_preset.value = data.expiry || 'custom';
    		}

    		form.expiry.value = expiry;
    		if (form.expiry_preset.value === 'custom') {
    			Morebits.quickForm.setElementVisibility(form.expiry.parentNode, true);
    		} else {
    			Morebits.quickForm.setElementVisibility(form.expiry.parentNode, false);
    		}
    	}

    	// boolean-flipped options, more at [[mw:API:Block]]
    	data.disabletalk = data.disabletalk !== undefined ? data.disabletalk : false;
    	data.hardblock = data.hardblock !== undefined ? data.hardblock : false;

    	// disable autoblock if blocking a bot
    	if (Twinkle.block.isRegistered && relevantUserName.search(/(?:بات\C|bot)\b/i) > 0) { // این عبارت باقاعده باید بهبود داده‌شود. الان اگر بعد از بات چیزی باشد، شناسایی نمی‌کند
    		data.autoblock = false;
    	}

    	$(form.field_block_options).find(':checkbox').each(function(i, el) {
    		// don't override original options if useInitialOptions is set
    		if (data.useInitialOptions && data[el.name] === undefined) {
    			return;
    		}

    		var check = data[el.name] === '' || !!data[el.name];
    		$(el).prop('checked', check);
    	});

    	if (data.prependReason && data.reason) {
    		form.reason.value = data.reason + '؛ ' + form.reason.value;
    	} else {
    		form.reason.value = data.reason || '';
    	}
    };

    Twinkle.block.callback.change_template = function twinkleblockcallbackChangeTemplate(e) {
    	var form = e.target.form, value = form.template.value, settings = Twinkle.block.blockPresetsInfo[value];
    	if (!$(form).find('[name=actiontype][value=block]').is(':checked')) {
    		if (settings.indefinite || settings.nonstandard) {
    			if (Twinkle.block.prev_template_expiry === null) {
    				Twinkle.block.prev_template_expiry = form.template_expiry.value || '';
    			}
    			form.template_expiry.parentNode.style.display = 'none';
    			form.template_expiry.value = 'indefinite';
    		} else if (form.template_expiry.parentNode.style.display === 'none') {
    			if (Twinkle.block.prev_template_expiry !== null) {
    				form.template_expiry.value = Twinkle.block.prev_template_expiry;
    				Twinkle.block.prev_template_expiry = null;
    			}
    			form.template_expiry.parentNode.style.display = 'block';
    		}
    		if (Twinkle.block.prev_template_expiry) {
    			form.expiry.value = Twinkle.block.prev_template_expiry;
    		}
    		Morebits.quickForm.setElementVisibility(form.notalk.parentNode, !settings.nonstandard);
    		Morebits.quickForm.setElementVisibility(form.noemail_template.parentNode, $(form).find('[name=actiontype][value=partial]').is(':checked') && !$(form).find('[name=actiontype][value=block]').is(':checked'));
    		Morebits.quickForm.setElementVisibility(form.nocreate_template.parentNode, $(form).find('[name=actiontype][value=partial]').is(':checked') && !$(form).find('[name=actiontype][value=block]').is(':checked'));
    	} else {
    		Morebits.quickForm.setElementVisibility(
    			form.blank_duration.parentNode,
    			!settings.indefinite && !settings.nonstandard
    		);
    	}
    	Morebits.quickForm.setElementVisibility(form.article.parentNode, !!settings.pageParam);
    	Morebits.quickForm.setElementVisibility(form.block_reason.parentNode, !!settings.reasonParam);

    	// Partial block
    	Morebits.quickForm.setElementVisibility(form.area.parentNode, $(form).find('[name=actiontype][value=partial]').is(':checked') && !$(form).find('[name=actiontype][value=block]').is(':checked'));

    	form.root.previewer.closePreview();
    };
    Twinkle.block.prev_template_expiry = null;
    Twinkle.block.prev_block_reason = null;
    Twinkle.block.prev_article = null;
    Twinkle.block.prev_reason = null;

    Twinkle.block.callback.preview = function twinkleblockcallbackPreview(form) {
    	var params = {
    		article: form.article.value,
    		blank_duration: form.blank_duration ? form.blank_duration.checked : false,
    		disabletalk: form.disabletalk.checked || (form.notalk ? form.notalk.checked : false),
    		expiry: form.template_expiry ? form.template_expiry.value : form.expiry.value,
    		hardblock: Twinkle.block.isRegistered ? form.autoblock.checked : form.hardblock.checked,
    		indefinite: (/indef|infinit|never|بی‌پایان|نامعین|\*|max/).test(form.template_expiry ? form.template_expiry.value : form.expiry.value),
    		reason: form.block_reason.value,
    		template: form.template.value,
    		partial: $(form).find('[name=actiontype][value=partial]').is(':checked'),
    		pagerestrictions: $(form.pagerestrictions).val() || [],
    		namespacerestrictions: $(form.namespacerestrictions).val() || [],
    		noemail: form.noemail.checked || (form.noemail_template ? form.noemail_template.checked : false),
    		nocreate: form.nocreate.checked || (form.nocreate_template ? form.nocreate_template.checked : false),
    		area: form.area.value
    	};

    	var templateText = Twinkle.block.callback.getBlockNoticeWikitext(params);

    	form.previewer.beginRender(templateText, 'بحث_کاربر:' + mw.config.get('wgRelevantUserName')); // Force wikitext/correct username
    };

    Twinkle.block.callback.evaluate = function twinkleblockCallbackEvaluate(e) {
    	var $form = $(e.target),
    		toBlock = $form.find('[name=actiontype][value=block]').is(':checked'),
    		toWarn = $form.find('[name=actiontype][value=template]').is(':checked'),
    		toPartial = $form.find('[name=actiontype][value=partial]').is(':checked'),
    		blockoptions = {}, templateoptions = {};

    	Twinkle.block.callback.saveFieldset($form.find('[name=field_block_options]'));
    	Twinkle.block.callback.saveFieldset($form.find('[name=field_template_options]'));

    	blockoptions = Twinkle.block.field_block_options;

    	templateoptions = Twinkle.block.field_template_options;
    	templateoptions.disabletalk = !!(templateoptions.disabletalk || blockoptions.disabletalk);
    	templateoptions.hardblock = !!blockoptions.hardblock;
    	delete blockoptions.expiry_preset; // remove extraneous

    	// Partial API requires this to be gone, not false or 0
    	if (toPartial) {
    		blockoptions.partial = templateoptions.partial = true;
    	}
    	templateoptions.pagerestrictions = $form.find('[name=pagerestrictions]').val() || [];
    	templateoptions.namespacerestrictions = $form.find('[name=namespacerestrictions]').val() || [];
    	// Format for API here rather than in saveFieldset
    	blockoptions.pagerestrictions = templateoptions.pagerestrictions.join('|');
    	blockoptions.namespacerestrictions = templateoptions.namespacerestrictions.join('|');

    	// use block settings as warn options where not supplied
    	templateoptions.summary = templateoptions.summary || blockoptions.reason;
    	templateoptions.expiry = templateoptions.template_expiry || blockoptions.expiry;

    	if (toBlock) {
    		if (blockoptions.partial) {
    			if (blockoptions.disabletalk && blockoptions.namespacerestrictions.indexOf('3') === -1) {
    				return alert('در قطع دسترسی‌های موردی نمی‌توان دسترسی صفحهٔ بحث راه گرفت؛ مگر آن که دسترسی به ویرایش در فضای نام بحث کاربر نیز گرفته شود!');
    			}
    			if (!blockoptions.namespacerestrictions && !blockoptions.pagerestrictions) {
    				if (!blockoptions.noemail && !blockoptions.nocreate) { // Blank entries technically allowed [[phab:T208645]]
    					return alert('هیچ صفحه یا فضای نامی انتخاب نشده‌است و محدودیتی برای ایمیل یا ایجاد حساب نیز اعمال نشده‌است؛ لطفاً برای قطع دسترسی موردی، دست کم یک گزینه را انتخاب کنید!');
    				} else if (!confirm('شما در حال قطع دسترسی کاربر بدون اعمال محدودیت ویرایشی در صفحه یا فضای نام خاصی هستید؛ آیا می‌خواهید ادامه دهید؟')) {
    					return;
    				}
    			}
    		}
    		if (!blockoptions.expiry) {
    			return alert('لطفاً زمان منقضی‌شدن را مشخص کنید!');
    		}
    		if (!blockoptions.reason) {
    			return alert('لطفاً دلیلی برای قطع دسترسی ارائه دهید!');
    		}

    		Morebits.simpleWindow.setButtonsEnabled(false);
    		Morebits.status.init(e.target);
    		var statusElement = new Morebits.status('اجرای قطع دسترسی');
    		blockoptions.action = 'block';
    		blockoptions.user = mw.config.get('wgRelevantUserName');

    		// boolean-flipped options
    		blockoptions.anononly = blockoptions.hardblock ? undefined : true;
    		blockoptions.allowusertalk = blockoptions.disabletalk ? undefined : true;

    		/*
    		  Check if block status changed while processing the form.

    		  There's a lot to consider here. list=blocks provides the
    		  current block status, but there are at least two issues with
    		  relying on it. First, the id doesn't update on a reblock,
    		  meaning the individual parameters need to be compared. This
    		  can be done roughly with JSON.stringify - we can thankfully
    		  rely on order from the server, although sorting would be
    		  fine if not - but falsey values are problematic and is
    		  non-ideal. More importantly, list=blocks won't indicate if a
    		  non-blocked user is blocked then unblocked. This should be
    		  exceedingy rare, but regardless, we thus need to check
    		  list=logevents, which has a nicely updating logid
    		  parameter. We can't rely just on that, though, since it
    		  doesn't account for blocks that have expired on their own.

    		  As such, we use both. Using some ternaries, the logid
    		  variables are false if there's no logevents, so if they
    		  aren't equal we defintely have a changed entry (send
    		  confirmation). If they are equal, then either the user was
    		  never blocked (the block statuses will be equal, no
    		  confirmation) or there's no new block, in which case either
    		  a block expired (different statuses, confirmation) or the
    		  same block is still active (same status, no confirmation).
    		*/
    		api.get({
    			format: 'json',
    			action: 'query',
    			list: 'blocks|logevents',
    			letype: 'block',
    			lelimit: 1,
    			letitle: 'کاربر:' + blockoptions.user,
    			bkusers: blockoptions.user
    		}).then(function(data) {
    			var block = data.query.blocks[0];
    			var logevents = data.query.logevents[0];
    			var logid = data.query.logevents.length ? logevents.logid : false;

    			if (logid !== Twinkle.block.blockLogId || !!block !== !!Twinkle.block.currentBlockInfo) {
    				var message = 'وضعیت قطع دسترسی ' + mw.config.get('wgRelevantUserName') + ' تغییر یافت. ';
    				if (block) {
    					message += 'وضعیت تازه: ';
    				} else {
    					message += 'آخرین مدخل: ';
    				}

    				var logExpiry = '';
    				if (logevents.params.duration) {
    					if (logevents.params.duration === 'infinity') {
    						logExpiry = 'نامعین';
    					} else {
    						var expiryDate = new Morebits.date(logevents.params.expiry);
    						logExpiry += (expiryDate.isBefore(new Date()) ? '، منقضی‌شده ' : ' تا ') + expiryDate.calendar();
    					}
    				} else { // no duration, action=unblock, just show timestamp
    					logExpiry = ' ' + new Morebits.date(logevents.timestamp).calendar();
    				}

    				message += 'به‌دلیل «' + logevents.comment + '» برای مدتی ' + logExpiry + ' توسط ' + logevents.user + ' ' + Morebits.string.toUpperCaseFirstChar(logevents.action) === 'block' ? 'بسته' : 'block' + ' شده‌است. آیا می‌خواهید تنظیمات خود را جایگزین کنید؟';

    			/*	message += Morebits.string.toUpperCaseFirstChar(logevents.action) + 'ed by ' + logevents.user + logExpiry +
    					' for "' + logevents.comment + '". Do you want to override with your settings?'; // localized above */

    				if (!confirm(message)) {
    					Morebits.status.info('اعمال قطع دسترسی', 'توسط کاربر لغو شد'); // localized
    					return;
    				}
    				blockoptions.reblock = 1; // Writing over a block will fail otherwise
    			}
    			// execute block
    			blockoptions.token = mw.user.tokens.get('csrfToken');
    			var mbApi = new Morebits.wiki.api('اعمال قطع دسترسی', blockoptions, function() { // localized
    				statusElement.info('کامل شد'); // localized
    				if (toWarn) {
    					Twinkle.block.callback.issue_template(templateoptions);
    				}
    			});
    			mbApi.post();
    		});
    	} else if (toWarn) {
    		Morebits.simpleWindow.setButtonsEnabled(false);

    		Morebits.status.init(e.target);
    		Twinkle.block.callback.issue_template(templateoptions);
    	} else {
    		return alert('لطفاً کاری برای توینکل تعیین کنید تا انجامش دهد!');
    	}
    };

    Twinkle.block.callback.issue_template = function twinkleblockCallbackIssueTemplate(formData) {
    	var userTalkPage = 'بحث_کاربر:' + mw.config.get('wgRelevantUserName');

    	var params = $.extend(formData, {
    		messageData: Twinkle.block.blockPresetsInfo[formData.template],
    		reason: Twinkle.block.field_template_options.block_reason,
    		disabletalk: Twinkle.block.field_template_options.notalk,
    		noemail: Twinkle.block.field_template_options.noemail_template,
    		nocreate: Twinkle.block.field_template_options.nocreate_template
    	});

    	Morebits.wiki.actionCompleted.redirect = userTalkPage;
    	Morebits.wiki.actionCompleted.notice = 'عمل انجام شد، بارگیری صفحهٔ بحث کاربر تا چند ثانیهٔ دیگر'; // localized

    	var wikipedia_page = new Morebits.wiki.page(userTalkPage, 'ویرایش صفحهٔ بحث کاربر');
    	wikipedia_page.setCallbackParameters(params);
    	wikipedia_page.setFollowRedirect(true);
    	wikipedia_page.load(Twinkle.block.callback.main);
    };

    Twinkle.block.callback.getBlockNoticeWikitext = function(params) {
    	var text = '{{', settings = Twinkle.block.blockPresetsInfo[params.template];
    	if (!settings.nonstandard) {
    		text += 'subst:' + params.template;
    		if (params.article && settings.pageParam) {
    			text += '|page=' + params.article;
    		}

    		if (!/te?mp|^\s*$|min/.exec(params.expiry)) {
    			if (params.indefinite) {
    				text += '|indef=yes';
    			} else if (!params.blank_duration) {
    				text += '|time=' + params.expiry;
    			}
    		}

    		if (!Twinkle.block.isRegistered && !params.hardblock) {
    			text += '|anon=yes';
    		}

    		if (params.reason) {
    			text += '|reason=' + params.reason;
    		}
    		if (params.disabletalk) {
    			text += '|notalk=yes';
    		}

    		// Currently, all partial block templates are "standard"
    		// Building the template, however, takes a fair bit of logic
    		if (params.partial) {
    			if (params.pagerestrictions.length || params.namespacerestrictions.length) {
    				var makeSentence = function (array) {
    					if (array.length < 3) {
    						return array.join(' و ');
    					}
    					var last = array.pop();
    					return array.join('، ') + ' و ' + last;

    				};
    				text += '|area=' + (params.indefinite ? 'اختصاصاً ' : 'اختصاصاً از ');
    				if (params.pagerestrictions.length) {
    					text += 'صفحه‌های (' + makeSentence(params.pagerestrictions.map(function(p) {
    						return '[[:' + p + ']]';
    					}));
    					text += params.namespacerestrictions.length ? ') و به‌طور ویژه از ' : ')';
    				}
    				if (params.namespacerestrictions.length) {
    					// 1 => Talk, 2 => User, etc.
    					var namespaceNames = params.namespacerestrictions.map(function(id) {
    						return menuFormattedNamespaces[id];
    					});
    					text += '[[ویکی‌پدیا:فضای نام|فضا(های) نام]] (' + makeSentence(namespaceNames) + ')'; // localized
    				}
    			} else if (params.area) {
    				text += '|area=' + params.area;
    			} else {
    				if (params.noemail) {
    					text += '|email=yes';
    				}
    				if (params.nocreate) {
    					text += '|accountcreate=yes';
    				}
    			}
    		}
    	} else {
    		text += params.template;
    	}

    	if (settings.sig) {
    		text += '|sig=' + settings.sig;
    	}
    	return text + '}}';
    };

    Twinkle.block.callback.main = function twinkleblockcallbackMain(pageobj) {
    	var text = pageobj.getPageText(),
    		params = pageobj.getCallbackParameters(),
    		messageData = params.messageData,
    		date = new Morebits.date(pageobj.getLoadTime());

    	var dateHeaderRegex = date.monthHeaderRegex(), dateHeaderRegexLast, dateHeaderRegexResult;
    	while ((dateHeaderRegexLast = dateHeaderRegex.exec(text)) !== null) {
    		dateHeaderRegexResult = dateHeaderRegexLast;
    	}
    	// If dateHeaderRegexResult is null then lastHeaderIndex is never checked. If it is not null but
    	// \n== is not found, then the date header must be at the very start of the page. lastIndexOf
    	// returns -1 in this case, so lastHeaderIndex gets set to 0 as desired.
    	var lastHeaderIndex = text.lastIndexOf('\n==') + 1;

    	if (text.length > 0) {
    		text += '\n\n';
    	}

    	params.indefinite = (/indef|infinit|never|\*|max/).test(params.expiry);

    	if (Twinkle.getPref('blankTalkpageOnIndefBlock') && params.template !== 'uw-lblock' && params.indefinite) {
    		Morebits.status.info('اطلاع‌رسانی', 'صفحهٔ بحث کاربر به درخواست شما خالی شد و یک بخش با عنوان سطح ۲ و تاریخ امروز در آن افزوده شد'); // localiezd
    		text = date.monthHeader() + '\n';
    	} else if (!dateHeaderRegexResult || dateHeaderRegexResult.index !== lastHeaderIndex) {
    		Morebits.status.info('اطلاع‌رسانی', 'یک بخش جدید با عنوان سطح ۲ و تاریخ امروز در صفحهٔ بحث افزوده خواهد شد، چرا که بخش مشابهی برای ماه جاری یافت نشد'); // localized
    		text += date.monthHeader() + '\n';
    	}

    	params.expiry = typeof params.template_expiry !== 'undefined' ? params.template_expiry : params.expiry;

    	text += Twinkle.block.callback.getBlockNoticeWikitext(params);

    	// build the edit summary
    	var summary = messageData.summary;
    	if (messageData.suppressArticleInSummary !== true && params.article) {
    		summary += ' بر [[:' + params.article + ']]'; // localized
    	}
    	summary += '.' + Twinkle.getPref('summaryAd');

    	pageobj.setPageText(text);
    	pageobj.setEditSummary(summary);
    	pageobj.setWatchlist(Twinkle.getPref('watchWarnings'));
    	pageobj.save();
    };

    })(jQuery);

    // </nowiki>

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