میڈیاویکی:Gadget-twinkleblock-2022.js

تفصیل کے لیے کھولیں کے بٹن پر کلک کریں یاددہانی: محفوظ کرنے کے بعد تازہ ترین تبدیلیوں کو دیکھنے کے لیے آپ کو اپنے براؤزر کا کیش صاف کرنا ہوگا۔

  • فائرفاکس/ سفاری: جب Reload پر کلک کریں تو Shift دبا کر رکھیں، یا Ctrl-F5 یا Ctrl-R دبائیں (Mac پر R- )
  • گوگل کروم: Ctrl-Shift-R دبائیں (Mac پر Shift-R-⌘)
  • انٹرنیٹ ایکسپلورر: جب Refresh پر کلک کریں تو Ctrl یا Ctrl-F5 دبائیں
  • اوپیرا: Tools → Preferences میں جائیں اور کیش صاف کریں

// <nowiki>


(function($) {

var api = new mw.Api(), relevantUserName, blockedUserName;
var menuFormattedNamespaces = $.extend({}, mw.config.get('wgFormattedNamespaces'));
menuFormattedNamespaces[0] = '(مرکزی)';
var logActionsTranslations = {
	'block': 'ممنوع',
	'reblock': 'دوبارہ پابندی',
	'unblock': 'پابندی ختم'
};

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

Twinkle.block = function twinkleblock() {
	relevantUserName = mw.config.get('wgRelevantUserName');
	// should show on Contributions or Block pages, anywhere there's a relevant user
	// Ignore ranges wider than the CIDR limit
	if (Morebits.userIsSysop && relevantUserName && (!Morebits.ip.isRange(relevantUserName) || Morebits.ip.validCIDR(relevantUserName))) {
		Twinkle.addPortletLink(Twinkle.block.callback, 'پابندی', 'tw-block', 'اس صارف پر پابندی لگائیں');
	}
};

Twinkle.block.callback = function twinkleblockCallback() {
	if (relevantUserName === mw.config.get('wgUserName') &&
			!confirm('آپ اپنے کھاتے پر پابندی لگا رہے ہیں! کیا آپ واقعی ایسا کرنا چاہتے ہیں؟')) {
		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('صارف ' + relevantUserName + ' پر پابندی لگائیں یا اس کی اطلاع بھیجیں');
	Window.setScriptName('پلک');
	Window.addFooterLink('پابندی سے متعلق سانچے', 'سانچہ:صا-پابندی/دستاویز/پابندی_کے_سانچے');
	Window.addFooterLink('پابندی لگانے کی حکمت عملی', 'وپ:پابندی');
	Window.addFooterLink('پابندی کی ترجیحات', 'وپ:پلک/ترجیحات#پابندی');
	Window.addFooterLink('رہنمائے پلک', ':en:WP:TW/DOC#block');
	Window.addFooterLink('آپ کے تاثرات', 'تبادلۂ خیال ویکیپیڈیا:پلک');

	// Always added, hidden later if actual user not blocked
	Window.addFooterLink('پابندی ہٹائیں', 'خاص:پابندی_ختم/' + relevantUserName, true);

	var form = new Morebits.quickForm(Twinkle.block.callback.evaluate);
	var actionfield = form.append({
		type: 'field',
		label: 'کارروائی کا انتخاب'
	});
	actionfield.append({
		type: 'checkbox',
		name: 'actiontype',
		event: Twinkle.block.callback.change_action,
		list: [
			{
				label: 'صارف پر پابندی لگائیں',
				value: 'block',
				tooltip: 'دیے گئے اختیارات کی مدد سے متعلقہ صارف پر پابندی لگائیں۔ اگر جزوی پابندی کو منتخب نہ کیا جائے تو کلی پابندی لگا دی جائے گی۔',
				checked: true
			},
			{
				label: 'جزوی پابندی',
				value: 'partial',
				tooltip: 'جزوی پابندی اور اس کے سانچوں کو فعال کیجیے۔',
				checked: Twinkle.getPref('defaultToPartialBlocks') // Overridden if already blocked
			},
			{
				label: 'صارف کے تبادلۂ خیال صفحہ پر پابندی کا سانچہ لگائیں',
				value: 'template',
				tooltip: 'اگر پابندی لگانے والا منتظم ممنوع صارف کے تبادلۂ خیال صفحہ پر پابندی کا سانچہ لگانا بھول گیا ہو یا آپ ہی نے ابھی اس صارف پر پابندی عائد کی ہو اور اس کے تبادلۂ خیال صفحہ پر سانچہ نہ لگایا ہو تو مناسب سانچہ چسپاں کرنے کے لیے اس اختیار کو استعمال کر سکتے ہیں۔ جزوی پابندی کے سانچوں کے لیے جزوی پابندی کے خانہ کو فعال کیجیے۔',
				// Disallow when viewing the block dialog on an IP range
				checked: !Morebits.ip.isRange(relevantUserName),
				disabled: Morebits.ip.isRange(relevantUserName)
			}
		]
	});

	/*
	  Add option for IPv6 ranges smaller than /64 to upgrade to the 64
	  CIDR ([[WP:/64]]).  This is one of the few places where we want
	  wgRelevantUserName since this depends entirely on the original user.
	  In theory, we shouldn't use Morebits.ip.get64 here since since we want
	  to exclude functionally-equivalent /64s.  That'd be:
	  // if (mw.util.isIPv6Address(mw.config.get('wgRelevantUserName'), true) &&
	  // (mw.util.isIPv6Address(mw.config.get('wgRelevantUserName')) || parseInt(mw.config.get('wgRelevantUserName').replace(/^(.+?)\/?(\d{1,3})?$/, '$2'), 10) > 64)) {
	  In practice, though, since functionally-equivalent ranges are
	  (mis)treated as separate by MediaWiki's logging ([[phab:T146628]]),
	  using Morebits.ip.get64 provides a modicum of relief in thise case.
	*/
	var sixtyFour = Morebits.ip.get64(mw.config.get('wgRelevantUserName'));
	if (sixtyFour && sixtyFour !== mw.config.get('wgRelevantUserName')) {
		var block64field = form.append({
			type: 'field',
			label: 'رینج بلاک /64 میں تبدیل کریں',
			name: 'field_64'
		});
		block64field.append({
			type: 'div',
			style: 'margin-bottom: 0.5em',
			label: ['عموماً یہ رویہ مناسب ہے، گرچہ بہتر نہیں کہ ', $.parseHTML('<a target="_blank" href="' + mw.util.getUrl('WP:/64') + '">رینج /64 کو مسدود کر دیا جائے</a>')[0], ' (',
				$.parseHTML('<a target="_blank" href="' + mw.util.getUrl('خاص:شراکتیں/' + sixtyFour) + '">' + sixtyFour + '</a>)')[0], ')۔']
		});
		block64field.append({
			type: 'checkbox',
			name: 'block64',
			event: Twinkle.block.callback.change_block64,
			list: [{
				checked: Twinkle.getPref('defaultToBlock64'),
				label: 'رینج /64 پر پابندی عائد کریں',
				value: 'block64',
				tooltip: Morebits.ip.isRange(mw.config.get('wgRelevantUserName')) ? 'سانچہ چسپاں کرنے سے احتراز کیا جائے گا' : 'بھیجے جانے والے تمام سانچے اصل آئی پی پتے: ' + mw.config.get('wgRelevantUserName') + ' پر جائیں گے۔'
			}]
		});
	}

	form.append({ type: 'field', label: 'متعینہ وجوہات', name: 'field_preset' });
	form.append({ type: 'field', label: 'سانچہ جاتی اختیارات', name: 'field_template_options' });
	form.append({ type: 'field', label: 'پابندی کے اختیارات', name: 'field_block_options' });

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

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

	Twinkle.block.fetchUserInfo(function() {
		// Toggle initial partial state depending on prior block type,
		// will override the defaultToPartialBlocks pref
		if (blockedUserName === relevantUserName) {
			$(result).find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
		}

		// clean up preset data (defaults, etc.), done exactly once, must be before Twinkle.block.callback.change_action is called
		Twinkle.block.transformBlockPresets();

		// init the controls after user and block info have been fetched
		var evt = document.createEvent('Event');
		evt.initEvent('change', true, true);

		if (result.block64 && result.block64.checked) {
			// Calls the same change_action event once finished
			result.block64.dispatchEvent(evt);
		} else {
			result.actiontype[0].dispatchEvent(evt);
		}
	});
};

// Store fetched user data, only relevant if switching IPv6 to a /64
Twinkle.block.fetchedData = {};
// Processes the data from a a query response, separated from
// Twinkle.block.fetchUserInfo to allow reprocessing of already-fetched data
Twinkle.block.processUserInfo = function twinkleblockProcessUserInfo(data, fn) {
	var blockinfo = data.query.blocks[0],
		userinfo = data.query.users[0];
	// If an IP is blocked *and* rangeblocked, the above finds
	// whichever block is more recent, not necessarily correct.
	// Three seems... unlikely
	if (data.query.blocks.length > 1 && blockinfo.user !== relevantUserName) {
		blockinfo = data.query.blocks[1];
	}
	// Cache response, used when toggling /64 blocks
	Twinkle.block.fetchedData[userinfo.name] = data;

	Twinkle.block.isRegistered = !!userinfo.userid;
	if (Twinkle.block.isRegistered) {
		Twinkle.block.userIsBot = !!userinfo.groupmemberships && userinfo.groupmemberships.map(function(e) {
			return e.group;
		}).indexOf('bot') !== -1;
	} else {
		Twinkle.block.userIsBot = false;
	}

	if (blockinfo) {
		// handle frustrating system of inverted boolean values
		blockinfo.disabletalk = blockinfo.allowusertalk === undefined;
		blockinfo.hardblock = blockinfo.anononly === undefined;
	}
	// will undefine if no blocks present
	Twinkle.block.currentBlockInfo = blockinfo;
	blockedUserName = Twinkle.block.currentBlockInfo && Twinkle.block.currentBlockInfo.user;

	// Toggle unblock link if not the user in question; always first
	var unblockLink = document.querySelector('.morebits-dialog-footerlinks a');
	if (blockedUserName !== relevantUserName) {
		unblockLink.hidden = true, unblockLink.nextSibling.hidden = true; // link+trailing bullet
	} else {
		unblockLink.hidden = false, unblockLink.nextSibling.hidden = false; // link+trailing bullet
	}

	// Semi-busted on ranges, see [[phab:T270737]] and [[phab:T146628]].
	// Basically, logevents doesn't treat functionally-equivalent ranges
	// as equivalent, meaning any functionally-equivalent IP range is
	// misinterpreted by the log throughout.  Without logevents
	// redirecting (like Special:Block does) we would need a function to
	// parse ranges, which is a pain.  IPUtils has the code, but it'd be a
	// lot of cruft for one purpose.
	Twinkle.block.hasBlockLog = !!data.query.logevents.length;
	Twinkle.block.blockLog = Twinkle.block.hasBlockLog && data.query.logevents;
	// 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();
	}
};

Twinkle.block.fetchUserInfo = function twinkleblockFetchUserInfo(fn) {
	var query = {
		format: 'json',
		action: 'query',
		list: 'blocks|users|logevents',
		letype: 'block',
		lelimit: 1,
		letitle: 'صارف:' + relevantUserName,
		bkprop: 'expiry|reason|flags|restrictions|range|user',
		ususers: relevantUserName
	};

	// bkusers doesn't catch single IPs blocked as part of a range block
	if (mw.util.isIPAddress(relevantUserName, true)) {
		query.bkip = relevantUserName;
	} else {
		query.bkusers = relevantUserName;
		// groupmemberships only relevant for registered users
		query.usprop = 'groupmemberships';
	}

	api.get(query).then(function(data) {
		Twinkle.block.processUserInfo(data, fn);
	}, function(msg) {
		Morebits.status.init($('div[name="currentblock"] span').last()[0]);
		Morebits.status.warn('صارف کی معلومات نہیں مل سکیں', msg);
	});
};

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_block64 = function twinkleblockCallbackChangeBlock64(e) {
	var $form = $(e.target.form), $block64 = $form.find('[name=block64]');

	// Show/hide block64 button
	// Single IPv6, or IPv6 range smaller than a /64
	var priorName = relevantUserName;
	if ($block64.is(':checked')) {
		relevantUserName = Morebits.ip.get64(mw.config.get('wgRelevantUserName'));
	} else {
		relevantUserName = mw.config.get('wgRelevantUserName');
	}
	// No templates for ranges, but if the original user is a single IP, offer the option
	// (done separately in Twinkle.block.callback.issue_template)
	var originalIsRange = Morebits.ip.isRange(mw.config.get('wgRelevantUserName'));
	$form.find('[name=actiontype][value=template]').prop('disabled', originalIsRange).prop('checked', !originalIsRange);

	// Refetch/reprocess user info then regenerate the main content
	var regenerateForm = function() {
		// Tweak titlebar text.  In theory, we could save the dialog
		// at initialization and then use `.setTitle` or
		// `dialog('option', 'title')`, but in practice that swallows
		// the scriptName and requires `.display`ing, which jumps the
		// window.  It's just a line of text, so this is fine.
		var titleBar = document.querySelector('.ui-dialog-title').firstChild.nextSibling;
		titleBar.nodeValue = titleBar.nodeValue.replace(priorName, relevantUserName);
		// Tweak unblock link
		var unblockLink = document.querySelector('.morebits-dialog-footerlinks a');
		unblockLink.href = unblockLink.href.replace(priorName, relevantUserName);
		unblockLink.title = unblockLink.title.replace(priorName, relevantUserName);

		// Correct partial state
		$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.getPref('defaultToPartialBlocks'));
		if (blockedUserName === relevantUserName) {
			$form.find('[name=actiontype][value=partial]').prop('checked', Twinkle.block.currentBlockInfo.partial === '');
		}

		// Set content appropriately
		Twinkle.block.callback.change_action(e);
	};

	if (Twinkle.block.fetchedData[relevantUserName]) {
		Twinkle.block.processUserInfo(Twinkle.block.fetchedData[relevantUserName], regenerateForm);
	} else {
		Twinkle.block.fetchUserInfo(regenerateForm);
	}
};

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);

	// Add current block parameters as default preset
	var prior = { label: 'سابقہ پابندی' };
	if (blockedUserName === relevantUserName) {
		Twinkle.block.blockPresetsInfo.prior = Twinkle.block.currentBlockInfo;
		// value not a valid template selection, chosen below by setting templateName
		prior.list = [{ label: 'سابقہ پابندی کی ترتیبات', value: 'prior', selected: true }];

		// Arrays of objects are annoying to check
		if (!blockGroup.some(function(bg) {
			return bg.label === prior.label;
		})) {
			blockGroup.push(prior);
		}

		// Always ensure proper template exists/is selected when switching modes
		if (partialBox) {
			Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-pblockindef' : 'uw-pblock';
		} else {
			if (!Twinkle.block.isRegistered) {
				Twinkle.block.blockPresetsInfo.prior.templateName = 'uw-ablock';
			} else {
				Twinkle.block.blockPresetsInfo.prior.templateName = Morebits.string.isInfinity(Twinkle.block.currentBlockInfo.expiry) ? 'uw-blockindef' : 'uw-block';
			}
		}
	} else {
		// But first remove any prior prior
		blockGroup = blockGroup.filter(function(bg) {
			return bg.label !== prior.label;
		});
	}

	// Can be in preset or template field, so the old one in the template
	// field will linger. No need to keep the old value around, so just
	// remove it; saves trouble when hiding/evaluating
	$form.find('[name=dstopic]').parent().remove();

	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: 'وجہ منتخب کریں:',
			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' });
		field_block_options.append({ type: 'div', name: 'currentblock', label: ' ' });
		field_block_options.append({ type: 'div', name: 'hasblocklog', label: ' ' });
		field_block_options.append({
			type: 'select',
			name: 'expiry_preset',
			label: 'مدت:',
			event: Twinkle.block.callback.change_expiry,
			list: [
				{ label: 'شخصی', value: 'custom', selected: true },
				{ label: 'دائمی', value: 'infinity' },
				{ label: '3 گھنٹے', value: '3 hours' },
				{ label: '12 گھنٹے', value: '12 hours' },
				{ label: '24 گھنٹے', value: '24 hours' },
				{ label: '31 گھنٹے', value: '31 hours' },
				{ label: '36 گھنٹے', value: '36 hours' },
				{ label: '48 گھنٹے', value: '48 hours' },
				{ label: '60 گھنٹے', value: '60 hours' },
				{ label: '72 گھنٹے', value: '72 hours' },
				{ label: '1 ہفتہ', value: '1 week' },
				{ label: '2 ہفتے', value: '2 weeks' },
				{ label: '1 مہینہ', value: '1 month' },
				{ label: '3 مہینے', value: '3 months' },
				{ label: '6 مہینے', value: '6 months' },
				{ label: '1 سال', value: '1 year' },
				{ label: '2 برس', value: '2 years' },
				{ label: '3 برس', value: '3 years' }
			]
		});
		field_block_options.append({
			type: 'input',
			name: 'expiry',
			label: 'شخصی مدت اختتام',
			tooltip: 'آپ اضافی وقتوں کو بھی استعمال کر سکتے ہیں، مثلاً «1 منٹ» یا «19 دن»، نیز مطلق وقت «yyyymmddhhmm» بھی درج کر سکتے ہیں (مثلاً: «200602011405» 1 فروری 2006ء 14:05 یوٹی سی ہوا)۔',
			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: 'مخصوص صفحات میں ترمیم پر پابندی',
				value: '',
				tooltip: 'آخری حد دس صفحے'
			});
			var ns = field_block_options.append({
				type: 'select',
				multiple: true,
				name: 'namespacerestrictions',
				label: 'نامہائے فضا میں پابندی',
				value: '',
				tooltip: 'ان نامہائے فضا میں ترمیم پر پابندی'
			});
			$.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: 'کھاتہ بنانے پر پابندی',
				name: 'nocreate',
				value: '1'
			},
			{
				checked: Twinkle.block.field_block_options.noemail,
				label: 'برقی خط بھیجنے پر پابندی',
				name: 'noemail',
				value: '1'
			},
			{
				checked: Twinkle.block.field_block_options.disabletalk,
				label: 'پابندی کے دوران میں اپنے تبادلۂ خیال صفحہ میں ترمیم پر پابندی',
				name: 'disabletalk',
				value: '1',
				tooltip: partialBox ? 'اگر جزوی پابندی لگائی جا رہی ہے تو اسے منتخب نہ کریں۔' : ''
			}
		];

		if (Twinkle.block.isRegistered) {
			blockoptions.push({
				checked: Twinkle.block.field_block_options.autoblock,
				label: 'صارف کے زیر استعمال تمام آئی پی پتوں پر خودکار پابندی (سخت پابندی)',
				name: 'autoblock',
				value: '1'
			});
		} else {
			blockoptions.push({
				checked: Twinkle.block.field_block_options.hardblock,
				label: 'داخل شدہ صارفین کے لیے اس آئی پی پتے کے ذریعہ ترمیم کاری پر پابندی (سخت پابندی)',
				name: 'hardblock',
				value: '1'
			});
		}

		blockoptions.push({
			checked: Twinkle.block.field_block_options.watchuser,
			label: 'صارف کے صارف اور تبادلۂ خیال صفحات کو زیر نظر رکھیں',
			name: 'watchuser',
			value: '1'
		});

		field_block_options.append({
			type: 'checkbox',
			name: 'blockoptions',
			list: blockoptions
		});
		field_block_options.append({
			type: 'textarea',
			label: 'وجہ (نوشتۂ پابندی میں اندراج کے لیے):',
			name: 'reason',
			tooltip: 'پہلے سے موجود وجوہات میں مفید تفصیلات ضرور شامل کریں۔',
			value: Twinkle.block.field_block_options.reason
		});

		field_block_options.append({
			type: 'div',
			name: 'filerlog_label',
			label: 'مزید دیکھیے:',
			style: 'display:inline-block;font-style:normal !important',
			tooltip: '«مزید دیکھیے» کا پیغام بھی جوڑیں جس میں اس جانب اشارہ ہو کہ حذف شدہ شراکتوں وغیرہ نے پابندی عائد کرنے کا فیصلہ کرنے پر کس طرح مجبور کیا۔'
		});
		field_block_options.append({
			type: 'checkbox',
			name: 'filter_see_also',
			event: Twinkle.block.callback.toggle_see_alsos,
			style: 'display:inline-block; margin-left:5px',
			list: [
				{
					label: 'نوشتۂ مقطر',
					checked: false,
					value: 'نوشتۂ مقطر'
				}
			]
		});
		field_block_options.append({
			type: 'checkbox',
			name: 'deleted_see_also',
			event: Twinkle.block.callback.toggle_see_alsos,
			style: 'display:inline-block',
			list: [
				{
					label: 'حذف شدہ شراکتیں',
					checked: false,
					value: 'حذف شدہ شراکتیں'
				}
			]
		});

		// Yet-another-logevents-doesn't-handle-ranges-well
		if (blockedUserName === relevantUserName) {
			field_block_options.append({ type: 'hidden', name: 'reblock', value: '1' });
		}
	}

	// grab discretionary sanctions list from en-wiki
	/* Twinkle.block.dsinfo = Morebits.wiki.getCachedJson('Template:Ds/topics.json');

	Twinkle.block.dsinfo.then(function(dsinfo) {
		var $select = $('[name="dstopic"]');
		var $options = $.map(dsinfo, function (value, key) {
			return $('<option>').val(value.code).text(key).prop('label', key);
		});
		$select.append($options);
	}); */

	// DS selection visible in either the template field set or preset,
	// joint settings saved here
	/* var dsSelectSettings = {
		type: 'select',
		name: 'dstopic',
		label: 'DS topic',
		value: '',
		tooltip: 'If selected, it will inform the template and may be added to the blocking message',
		event: Twinkle.block.callback.toggle_ds_reason
	}; */
	if (templateBox) {
		field_template_options = new Morebits.quickForm.element({ type: 'field', label: 'سانچہ جاتی اختیارات', name: 'field_template_options' });
		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
		});

		// Only visible for aeblock and aepblock, toggled in change_template
		// field_template_options.append(dsSelectSettings);

		field_template_options.append({
			type: 'input',
			name: 'article',
			label: 'مربوط مضمون',
			value: '',
			tooltip: 'اطلاع میں کسی مضمون کا ربط بھی درج کیا جا سکتا، خصوصاً اس وقت جب مضمون ہی خلل کا باعث ہو۔ ربط درج نہ کرنا ہو تو اسے خالی چھوڑ دیں۔'
		});

		// Only visible if partial and not blocking
		field_template_options.append({
			type: 'input',
			name: 'area',
			label: 'پابندی کا دائرہ',
			value: '',
			tooltip: 'ان صفحات یا نامہائے فضا کی وضاحت جن میں ترمیم کرنے سے صارف کو روک دیا گیا ہے۔'
		});

		if (!blockBox) {
			field_template_options.append({
				type: 'input',
				name: 'template_expiry',
				label: 'پابندی کی مدت:',
				value: '',
				tooltip: 'صارف کی پابندی ختم ہونے کی مدت، مثلاً 24 گھنٹے، 2 ہفتے، دائمی وغیرہ۔۔۔'
			});
		}
		field_template_options.append({
			type: 'input',
			name: 'block_reason',
			label: '«آپ پر پابندی عائد کرنے کی وجہ۔۔۔»',
			tooltip: 'وجہ درج کرنا اختیاری ہے، آپ کی درج کردہ وجہ مندرج وجوہات کی جگہ پر رکھی جائے گی۔ یہ اختیار محض عام پاپندی کے سانچوں کے لیے دستیاب ہے۔',
			value: Twinkle.block.field_template_options.block_reason
		});

		if (blockBox) {
			field_template_options.append({
				type: 'checkbox',
				name: 'blank_duration',
				list: [
					{
						label: 'سانچہ میں مدت اختتام شامل نہ کریں',
						checked: Twinkle.block.field_template_options.blank_duration,
						tooltip: 'مدت شامل کرنے کی بجائے سانچہ میں یہ عبارت شامل کریں «آپ پر عارضی پابندی عائد کی گئی ہے، اس کی وجہ۔۔۔»'
					}
				]
			});
		} else {
			field_template_options.append({
				type: 'checkbox',
				list: [
					{
						label: 'تبادلۂ خیال تک رسائی ختم کریں',
						name: 'notalk',
						checked: Twinkle.block.field_template_options.notalk,
						tooltip: 'اس اختیار کو فعال کرنے پر سانچہ میں یہ اطلاع شامل ہو جائے گی کہ تبادلۂ صفحہ تک صارف کی رسائی کو ختم کر دیا گیا ہے۔'
					},
					{
						label: 'برقی خط بھیجنے پر پابندی لگائیں',
						name: 'noemail_template',
						checked: Twinkle.block.field_template_options.noemail_template,
						tooltip: 'پابندی کا دائرہ نہ بتایا گیا ہو تو پابندی کی اطلاع میں یہ اضافہ ضرور کریں کہ صارف کو برقی خطوط بھیجنے سے بھی روک دیا گیا ہے۔'
					},
					{
						label: 'کھاتہ بنانے پر پابندی لگائیں',
						name: 'nocreate_template',
						checked: Twinkle.block.field_template_options.nocreate_template,
						tooltip: 'پابندی کا دائرہ نہ بتایا گیا ہو تو پابندی کی اطلاع میں یہ اضافہ ضرور کریں کہ صارف کو کھاتے بنانے سے بھی روک دیا گیا ہے۔'
					}
				]
			});
		}

		var $previewlink = $('<a id="twinkleblock-preview-link">نمائش</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' });
	} else if (field_preset) {
		// Only visible for arbitration enforcement, toggled in change_preset
		// field_preset.append(dsSelectSettings);
	}

	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('fieldset[name="field_64"]').show();


		$form.find('[name=pagerestrictions]').select2({
			width: '100%',
			placeholder: 'جن صفحات سے صارف کو باز رکھنا ہے',
			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(
			// 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();
		$form.find('fieldset[name="field_64"]').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();
	}

	// Any block, including ranges
	if (Twinkle.block.currentBlockInfo) {
		// false for an ip covered by a range or a smaller range within a larger range;
		// true for a user, single ip block, or the exact range for a range block
		var sameUser = blockedUserName === relevantUserName;

		Morebits.status.init($('div[name="currentblock"] span').last()[0]);
		var statusStr = relevantUserName + ' پر ' + (Twinkle.block.currentBlockInfo.partial === '' ? 'جزوی پابندی عائد ہے' : 'کلّی پابندی عائد ہے');

		// Range blocked
		if (Twinkle.block.currentBlockInfo.rangestart !== Twinkle.block.currentBlockInfo.rangeend) {
			if (sameUser) {
				statusStr += ' رینج بلاک کے طور پر';
			} else {
				statusStr += (Morebits.ip.get64(relevantUserName) === blockedUserName ? ' /64' : '') + ' رینج بلاک میں';
				// Link to the full range
				var $rangeblockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('خاص:نوشتہ', {action: 'view', page: blockedUserName, type: 'block'}) + '">' + blockedUserName + '</a>)'));
				statusStr += 'پر پابندی عائد ہے (' + $rangeblockloglink.html() + ')';
			}
		}

		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 = 'اس فارم کی مدد سے';
		if (sameUser) {
			infoStr += ' پابندی کی نوعیت کو تبدیل کیا جا سکتا ہے';
			if (Twinkle.block.currentBlockInfo.partial === undefined && partialBox) {
				infoStr += ' اور جزوی پابندی عائد جا سکتی ہے';
			} else if (Twinkle.block.currentBlockInfo.partial === '' && !partialBox) {
				infoStr += ' اور کلی پابندی لگائی جا سکتی ہے';
			}
			infoStr += '۔';
		} else {
			infoStr += ' دوسری ' + (partialBox ? 'جزوی ' : '') + 'پابندی لگائی جا سکتی ہے۔';
		}

		Morebits.status.warn(statusStr, infoStr);

		// Default to the current block conditions on intial form generation
		Twinkle.block.callback.update_form(e, Twinkle.block.currentBlockInfo);
	}

	// This is where T146628 really comes into play: a rangeblock will
	// only return the correct block log if wgRelevantUserName is the
	// exact range, not merely a funtional equivalent
	if (Twinkle.block.hasBlockLog) {
		var $blockloglink = $('<span>').append($('<a target="_blank" href="' + mw.util.getUrl('خاص:نوشتہ', {action: 'view', page: relevantUserName, type: 'block'}) + '">نوشتۂ پابندی</a>)'));
		if (!Twinkle.block.currentBlockInfo) {
			var lastBlockAction = Twinkle.block.blockLog[0];
			if (lastBlockAction.action === 'unblock') {
				$blockloglink.append(' (' + new Morebits.date(lastBlockAction.timestamp).calendar('utc') + ' کو پابندی ہٹائی گئی)');
			} else { // block or reblock
				$blockloglink.append(' (' + lastBlockAction.params.duration + '، تاریخ اختتام: ' + new Morebits.date(lastBlockAction.params.expiry).calendar('utc') + ')');
			}
		}

		Morebits.status.init($('div[name="hasblocklog"] span').last()[0]);
		Morebits.status.warn(Twinkle.block.currentBlockInfo ? 'سابقہ پابندیاں' : 'اس ' + (Morebits.ip.isRange(relevantUserName) ? 'رینج' : 'صارف') + ' پر ماضی میں پابندی لگائی گئی تھی', $blockloglink[0]);
	}

	// Make sure all the fields are correct based on initial defaults
	if (blockBox) {
		Twinkle.block.callback.change_preset(e);
	} else if (templateBox) {
		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 = {
	'قطع دسترسی ناشناس': {
		expiry: '31 hours',
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{قطع دسترسی ناشناس}}',
		sig: '~~~~'
	},
	'قطع دسترسی ناشناس - مدرسه': {
		expiry: '36 hours',
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{قطع دسترسی ناشناس}} <!-- احتمالاً مستقر در یک دانشگاه طبق شواهد رفتاری -->',
		templateName: 'قطع دسترسی ناشناس',
		sig: '~~~~'
	},
	'پروکسی باز': {
		expiry: '1 year',
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		hardblock: true,
		reason: '{{پروکسی باز}}',
		sig: null
	},
	'قطع دسترسی بازرسی کاربر': {
		expiry: '1 week',
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{قطع دسترسی بازرسی کاربر}}',
		sig: '~~~~'
	},
	'بندایش بازرسی کاربر-حساب کاربری': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{بندایش بازرسی کاربر-حساب کاربری}}',
		sig: '~~~~'
	},
	'قطع دسترسی بازرسی کاربر-کلی': {
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{قطع دسترسی بازرسی کاربر-کلی}}',
		sig: '~~~~'
	},
	'میزبانی‌وب‌سرور': {
		expiry: '1 year',
		forAnonOnly: true,
		nonstandard: true,
		reason: '{{میزبانی‌وب‌سرور}}',
		sig: null
	},
	'قطع دسترسی پنهان‌گر': {
		autoblock: true,
		expiry: 'infinity',
		nocreate: true,
		nonstandard: true,
		reason: '{{هبک-قطع دسترسی پنهان‌گر}}',
		sig: '~~~~'
	},
	'قطع دسترسی مدرسه': {
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{قطع دسترسی مدرسه}}',
		sig: '~~~~'
	},
	'بستن فهرست سیاه': {
		forAnonOnly: true,
		expiry: '1 month',
		disabletalk: true,
		nocreate: true,
		reason: '{{هبک-بستن فهرست سیاه}} <!-- ویرایشگر تنها اقدام به افزودن پیوندهای قرارگرفته در فهرست سیاه می‌کند؛ [[ویژه:سیاهه‌ها/spamblacklist]] را ببینید -->'
	},
	'قطع دسترسی بازه آی‌پی': {
		reason: '{{قطع دسترسی بازه آی‌پی}}',
		nocreate: true,
		nonstandard: true,
		forAnonOnly: true,
		sig: '~~~~'
	},
	'تور': {
		expiry: '1 year',
		forAnonOnly: true,
		nonstandard: true,
		reason: '{{تور}}',
		sig: null
	},
	'میزبان وب بسته‌شده': {
		expiry: '1 year',
		forAnonOnly: true,
		nonstandard: true,
		reason: '{{میزبان وب بسته‌شده}}',
		sig: null
	},
	// uw-prefixed (هبک)
	'هبک-قطع دسترسی ۳ب': {
		autoblock: true,
		expiry: '24 hours',
		nocreate: true,
		pageParam: true,
		reason: 'نقض [[وپ:۳ب|قاعدهٔ سه برگردان]]',
		summary: 'دسترسی ویرایشی شما به‌دلیل نقض [[وپ:۳ب|قاعدهٔ سه برگردان]] بسته شده است'
	},
	'هبک-قطع دسترسی ناشناس': {
		autoblock: true,
		expiry: '31 hours',
		forAnonOnly: true,
		nocreate: true,
		pageParam: true,
		reasonParam: true,
		summary: 'دسترسی ویرایشی نشانی آی‌پی شما بسته شده است',
		suppressArticleInSummary: true
	},
	'هبک-قطع دسترسی هرزنگاری': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: 'استفاده از ویکی‌پدیا برای [[وپ:هرز|هرزنگاری]] یا [[وپ:تبلیغ|تبلیغات]]',
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:منبر|تبلیغات یا ترویج]] بسته شده است'
	},
/*	'uw-aeblock': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: '[[WP:Arbitration enforcement|Arbitration enforcement]]',
		reasonParam: true,
		summary: 'You have been blocked from editing for violating an [[WP:Arbitration|arbitration decision]]'
	}, */
	'هبک-قطع دسترسی زندگان': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: 'نقض سیاست [[وپ:زندگی‌نامه زندگان|زندگی‌نامهٔ افراد زنده]]',
		summary: 'دسترسی ویرایشی شما به دلیل نقض [[وپ:زنده|سیاست زندگی‌نامهٔ افراد زنده]] ویکی‌پدیا بسته شده است'
	},
	'قطع دسترسی': {
		autoblock: true,
		expiry: '24 hours',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما بسته شده است',
		suppressArticleInSummary: true
	},
	'هبک-قطع دسترسی بی‌پایان': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است',
		suppressArticleInSummary: true
	},
	'هبک-قطع دسترسی بحث': {
		disabletalk: true,
		pageParam: true,
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما بسته شده است و دسترسی شما به صفحهٔ بحث‌تان نیز غیرفعال شده است',
		suppressArticleInSummary: true
	},
	'هبک-قطع دسترسی ربات': {
		forRegisteredOnly: true,
		pageParam: true,
		reason: 'راندن [[وپ:ربات|اسکریپت ربات]] بدون [[وپ:پرچم|مجوز]]',
		summary: 'دسترسی ویرایشی شما بسته شده است؛ زیرا به‌نظر می‌رسد که در حال راندن یک [[وپ:ربات|اسکریپت ربات]] بدون [[وپ:پرچم|کسب مجوز]] هستید'
	},
	'هبک-بستن نام کاربری ربات': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{هبک-بستن نام کاربری ربات}} <!-- نام کاربری مشابه نام ربات است؛ قطع دسترسی نرم -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا [[وپ:نام|نام کاربری]] شما نشان می‌دهد که این حساب یک [[وپ:ربات|حساب ربات]] است که در حال حاضر فاقد مجوز است'
	},
	'هبک-بستن سخت نام ربات': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: '{{هبک-بستن سخت نام ربات}} <!-- نام کاربری مشابه نام ربات است؛ قطع دسترسی سخت -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا نام کاربری شما آشکارا ناقض [[وپ:نام|سیاست نام کاربری]] است.'
	},
	'هبک-قطع دسترسی جنبش': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{هبک-قطع دسترسی جنبش}} <!-- نام کاربری نمایندهٔ یک سازمان ناسودبر است، قطع دسترسی نرم -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا به‌نظر می‌رسد که [[وپ:نام|نام کاربری]] شما نمایندهٔ یک گروه، سازمان، یا وبگاه است'
	},
	'هبک-بستن حساب به‌خطر افتاده': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: 'حساب به خطر افتاده',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا باور بر این است که [[وپ:امنیت|امنیت حساب کاربری شما]] به خطر افتاده است'
	},
	'هبک-قطع دسترسی حق تکثیر': {
		autoblock: true,
		expiry: 'infinity',
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:حق تکثیر|نقض حق تکثیر]]',
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:حت|نقض حق تکثیر]] ادامه‌دار بسته شده است'
	},
	'هبک-قطع دسترسی حذف محتوا': {
		autoblock: true,
		nocreate: true,
		reason: 'حذف مکرر محتوا',
		pageParam: true,
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:خ|حذف محتوای صفحه‌ها]] بسته شده است'
	},
	'هبک-قطع دسترسی اخلالگری': {
		autoblock: true,
		nocreate: true,
		reason: '[[وپ:ویرایش اخلالگرانه|ویرایش اخلالگرانه]]',
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:ویرایش اخلالگرانه|ویرایش اخلالگرانه]] بسته شده است'
	},
	'هبک-قطع دسترسی پالایه ویرایش': {
		autoblock: true,
		nocreate: true,
		reason: 'فعال‌سازی مکرر [[وپ:پالایه ویرایش|پالایهٔ ویرایش]]',
		summary: 'دسترسی ویرایشی شما به دلیل تکرار ویرایش‌های اخلالگرانه‌ای که مکرراً [[وپ:پالایه|پالایهٔ ویرایش]] را فعال کرده‌اند، بسته شده است'
	},
	'هبک-قطع دسترسی جنگ ویرایشی': {
		autoblock: true,
		expiry: '24 hours',
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:جنگ|جنگ ویرایشی]]',
		summary: 'دسترسی ویرایشی شما به‌منظور جلوگیری از [[وپ:ویرایش اخلالگرانه|اخلال]] بیشتر به‌واسطهٔ درگیر شدن شما در [[وپ:جنگ|جنگ ویرایشی]] بسته شده است'
	},
	'هبک-قطع دسترسی آزار': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:حمله شخصی ممنوع|حمله شخصی]] یا [[وپ:آزار|آزار و اذیت]]',
		summary: 'دسترسی ویرایشی شما به دلیل اقدام به [[وپ:آزار|آزار و اذیت]] کاربران دیگر بسته شده است'
	},
	'هبک-بستن دور زدن قطع دسترسی': {
		forAnonOnly: true,
		nocreate: true,
		reason: '[[وپ:دور زدن|دور زدن قطع دسترسی]]',
		summary: 'دسترسی ویرایشی نشانی آی‌پی شما بسته شده است؛ زیرا از آن برای [[وپ:دور زدن|دور زدن قطع دسترسی پیشین]] استفاده شده است'
	},
	'هبک-قطع دسترسی تهدید': {
		autoblock: true,
		expiry: 'infinity',
		nocreate: true,
		reason: '[[وپ:تهدید قانونی ممنوع|تهدید قانونی]]',
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:تهدید قانونی|تهدید قانونی یا اقدامات حقوقی]] بسته شده است'
	},
	'هبک-قطع دسترسی اینجا نه': {
		autoblock: true,
		expiry: 'infinity',
		nocreate: true,
		reason: 'واضح است که [[وپ:اینجا نه|برای کمک به دانشنامه اینجا نیست]]',
		forRegisteredOnly: true,
		summary: 'دسترسی ویرایشی شما بسته شده است؛ زیرا به‌نظر می‌رسد که [[وپ:اینجا نه|برای کمک به دانشنامه اینجا نیستید]]'
	},
	'هبک-قطع دسترسی بی‌معنی': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: 'ایجاد [[وپ:بی‌معنی|صفحه‌های بی‌معنی]] یا سایر صفحه‌های نامناسب',
		summary: 'دسترسی ویرایشی شما به دلیل ایجاد [[وپ:بی‌معنی|صفحه‌های بی‌معنی]] بسته شده است'
	},
	'هبک-قطع دسترسی حمله شخصی': {
		autoblock: true,
		expiry: '31 hours',
		nocreate: true,
		reason: '[[وپ:حمله|حملهٔ شخصی]] یا [[وپ:آزار|آزار و اذیت]]',
		summary: 'دسترسی ویرایشی شما به دلیل [[وپ:حمله|حملهٔ شخصی]] به کاربران دیگر بسته شده است'
	},
	'هبک-قطع دسترسی اسپم': {
		autoblock: true,
		nocreate: true,
		reason: 'استفاده از ویکی‌پدیا برای [[وپ:هرز|هرزنگاری]]',
		summary: 'دسترسی ویرایشی شما به دلیل استفاده از ویکی‌پدیا برای [[وپ:هرز|هرزنگاری]] بسته شده است'
	},
	'هبک-بستن حساب هرزنگار': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reason: 'حساب ایجاد شده برای [[وپ:هرز|هرزنگاری]] یا [[وپ:تبلیغ|تبلیغات]]',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا از حساب کاربری خود تنها برای [[وپ:هرز|هرزنگاری، تبلیغات یا ترویج]] استفاده کرده‌اید'
	},
	'هبک-قطع دسترسی شبکه اجتماعی': {
		autoblock: true,
		nocreate: true,
		pageParam: true,
		reason: 'استفاده از ویکی‌پدیا به‌عنوان یک [[وپ:فیسبوک نیست|وب‌نوشت، میزبان وب، شبکهٔ اجتماعی یا انجمن]]',
		summary: 'دسترسی ویرایشی شما به دلیل استفاده از صفحه‌های کاربری و/یا مقاله‌ها به‌عنوان [[وپ:فیسبوک نیست|وب‌نوشت، میزبان وب، شبکهٔ اجتماعی یا انجمن]] بسته شده است'
	},
	'هبک-قطع دسترسی زاپاس': {
		autoblock: true,
		forRegisteredOnly: true,
		nocreate: true,
		reason: 'سوءاستفاده از [[وپ:زاپاس‌بازی|چند حساب کاربری]]',
		summary: 'دسترسی ویرایشی شما به دلیل سوءاستفاده از [[وپ:زاپاس|چند حساب کاربر]] بسته شده است'
	},
	'هبک-قطع دسترسی نرم نام کاربری': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{هبک-قطع دسترسی نرم نام کاربری}} <!-- نام کاربری تبلیغاتی، قطع دسترسی نرم -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا [[وپ:نام|نام کاربری]] به گونه‌ای است که گویی این حساب نمایندهٔ یک گروه، سازمان یا وبگاه است'
	},
	'هبک-قطع دسترسی نرم هرزنگاری': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: '{{هبک-قطع دسترسی نرم هرزنگاری}} <!-- نام کاربری تبلیغاتی، ویرایش‌های تبلیغاتی -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا حساب کاربری شما تنها برای [[وپ:هرز|هرزنگاری یا تبلیغات]] استفاده شده و نام کاربری شما ناقض [[وپ:نام|سیاست نام کاربری]] است'
	},
	'بستن زاپاس': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: '[[وپ:زاپاس|زاپاس‌بازی]]',
		summary: 'دسترسی این حساب کاربری به‌عنوان یک [[وپ:زاپاس|حساب زاپاس]] ایجادشده با هدف نقض سیاست‌های ویکی‌پدیا، بسته شده است'
	},
	'بسته‌شده بدون دسترسی بحث-اعلان': {
		disabletalk: true,
		reason: 'گرفتن دسترسی بحث: استفادهٔ نادرست از صفحهٔ بحث کاربری در زمان بسته بودن',
		prependReason: true,
		summary: 'دسترسی شما به صفحهٔ بحث‌تان غیرفعال شده است',
		useInitialOptions: true
	},
	'هبک-قطع دسترسی نام کاربری': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{هبک-قطع دسترسی نام کاربری}} <!-- نقض سیاست نام کاربری، قطع دسترسی نرم -->',
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا نام کاربری شما ناقض [[وپ:نام|سیاست نام کاربری]] است'
	},
	'هبک-قطع دسترسی نام کاربری-تکراری': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{هبک-قطع دسترسی نام کاربری-تکراری}} <!-- نام کاربری بسیار مشابه نام یک کاربر دیگر است، قطع دسترسی نرم -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا [[وپ:نام|نام کاربری]] شما بسیار مشابه نام کاربری یک ویرایشگر دیگر در ویکی‌پدیا است'
	},
	'هبک-قطع دسترسی مطالب بدون منبع': {
		autoblock: true,
		expiry: '31 hours',
		nocreate: true,
		pageParam: true,
		reason: 'افزودن مکرر [[وپ:مقدارج|مطالب بدون منبع]]',
		summary: 'دسترسی ویرایشی شما به دلیل افزودن مداوم [[وپ:مقدارج|مطالب بدون منبع]] بسته شده است'
	},
	'هبک-بستن سخت نام کاربری': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: '{{هبک-بستن سخت نام کاربری}} <!-- نقض سیاست نام کاربری، قطع دسترسی سخت -->',
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا نام کاربری شما آشکارا ناقض [[وپ:نام|سیاست نام کاربری]] است'
	},
	'بستن نام واقعی': {
		expiry: 'infinity',
		forRegisteredOnly: true,
		reason: '{{بستن نام واقعی}} <!-- نام کاربری همنام با یک شخص سرشناس، قطع دسترسی نرم -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا [[وپ:نام|نام کاربری]] شما با نام یک شخص زندهٔ سرشناس یکسان است'
	},
	'هبک-بستن سخت نام کاربری-تکراری': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		reason: '{{هبک-بستن سخت نام کاربری-تکراری}} <!-- اقدام به جعل هویت کاربر دیگر، قطع دسترسی سخت -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا [[وپ:نام|نام کاربری]] شما منجر به جعل هویت یک کاربر قدیمی دیگر ویکی‌پدیا می‌شود'
	},
	'هبک-بستن نام کاربری دستمزد ': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:مزد|ویرایش در برابر دستمزد فاش نشده]] در تضاد با [[وپ:شا|شرایط استفادهٔ]] بنیاد ویکی‌مدیا',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا از حساب کاربری خود در تضاد با [[وپ:مزد|سیاست ویکی‌پدیا برای مشارکت در برابر دستمزد فاش‌نشده]] استفاده کرده‌اید'
	},
	'هبک-بستن نام کاربری خرابکاری': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reason: '{{هبک-بستن نام کاربری خرابکاری}} <!-- نقض سیاست نام کاربری، حساب ایجادشده برای خرابکاری -->',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا حساب کاربری شما [[وپ:حفخ|تنها برای خرابکاری استفاده شده]] و نام کاربری شما آشکارا ناقض [[وپ:نام|سیاست نام کاربری]] است'
	},
	'هبک-قطع دسترسی خرابکاری': {
		autoblock: true,
		expiry: '31 hours',
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:خرابکاری|خرابکاری]]',
		summary: 'دسترسی ویرایشی شما به‌منظور جلوگیری از ادامه‌یافتن [[وپ:خ|خرابکاری]] بسته شده است'
	},
	'هبک-قطع دسترسی حساب خرابکار': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: true,
		reason: '[[وپ:حساب ساخته‌شده برای خرابکاری|حساب ایجادشده برای خرابکاری]]',
		summary: 'دسترسی ویرایشی شما برای مدت نامعین بسته شده است؛ زیرا حساب کاربری شما [[وپ:حفخ|تنها برای خرابکاری ساخته شده است]]'
	},
	'زامبی پراکسی': {
		expiry: '1 month',
		forAnonOnly: true,
		nocreate: true,
		nonstandard: true,
		reason: '{{زامبی پراکسی}}',
		sig: null
	},

	// Begin partial block templates, accessed in Twinkle.block.blockGroupsPartial
	'هبک-بستن موردی ایجاد حساب': {
		autoblock: true,
		expiry: '48 hours',
		nocreate: true,
		pageParam: false,
		reasonParam: true,
		reason: 'سوءاستفاده از [[وپ:زاپاس‌بازی|چند حساب کاربری]]',
		summary: 'به‌دلیل سوءاستفاده از [[وپ:زاپاس|چند حساب کاربری]]، [[وپ:موردی|دسترسی ایجاد حساب برای شما بسته شده است]]'
	},
	'هبک-بستن موردی ایجاد حساب بی‌پایان': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: true,
		pageParam: false,
		reasonParam: true,
		reason: 'سوءاستفاده از [[وپ:زاپاس‌بازی|چند حساب کاربری]]',
		summary: 'به‌دلیل سوءاستفاده از [[وپ:زاپاس|چند حساب کاربری]]، [[WP:PB|دسترسی ایجاد حساب برای شما برای مدت نامعین بسته شده است]]'
	},
/*	'uw-aepblock': {
		autoblock: true,
		nocreate: false,
		pageParam: false,
		reason: '[[WP:Arbitration enforcement|Arbitration enforcement]]',
		reasonParam: true,
		summary: 'You have been [[WP:PB|partially blocked]] from editing for violating an [[WP:Arbitration|arbitration decision]]'
	}, */
	'هبک-بستن موردی ایمیل': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: false,
		noemail: true,
		pageParam: false,
		reasonParam: true,
		reason: '[[وپ:آزار|آزار و اذیت]] از طریق ایمیل',
		summary: 'به‌دلیل [[وپ:آزار|آزار و اذیت]] ویرایشگران دیگر، [[وپ:موردی|دسترسی شما به ارسال ایمیل بسته شده است]]'
	},
	'هبک-بستن موردی جنگ': {
		autoblock: true,
		expiry: '24 hours',
		nocreate: false,
		pageParam: false,
		reasonParam: true,
		reason: '[[وپ:جنگ ویرایشی|جنگ ویرایشی]]',
		summary: 'به‌منظور جلوگیری از ادامه‌یافتن [[وپ:ویرایش اخلالگرانه|اخلال]] به‌واسطهٔ [[وپ:جنگ|جنگ ویرایشی]]، دسترسی ویرایشی شما به برخی فضاهای خاص در دانشنامه [[وپ:موردی|به‌صورت موردی بسته شده است]]'
	},
	'هبک-بستن موردی': {
		autoblock: true,
		expiry: '24 hours',
		nocreate: false,
		pageParam: false,
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما به برخی فضاهای خاص دانشنامه [[وپ:موردی|به‌صورت موردی بسته شده است]]'
	},
	'هبک-بستن موردی بی‌پایان': {
		autoblock: true,
		expiry: 'infinity',
		forRegisteredOnly: true,
		nocreate: false,
		pageParam: false,
		reasonParam: true,
		summary: 'دسترسی ویرایشی شما به برخی فضاهای خاص دانشنامه برای مدت نامعین و [[وپ:موردی|به‌صورت موردی بسته شده است]]'
	}
};

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';
		settings.indefinite = settings.indefinite || Morebits.string.isInfinity(settings.expiry);

		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: 'قطع دسترسی ناشناس' },
			{ label: 'ناشناس - احتمالاً مدرسه', value: 'قطع دسترسی ناشناس - مدرسه' },
			{ label: 'قطع دسترسی مدرسه', value: 'قطع دسترسی مدرسه' },
			{ label: 'قطع دسترسی عمومی (دلیل سفارشی)', value: 'قطع دسترسی' }, // ends up being default for registered users
			{ label: 'قطع دسترسی عمومی (دلیل سفارشی) - آی‌پی', value: 'هبک-قطع دسترسی ناشناس', selected: true }, // set only when blocking IP
			{ label: 'قطع دسترسی عمومی (دلیل سفارشی) - بی‌پایان', value: 'هبک-قطع دسترسی بی‌پایان' },
			{ label: 'ویرایش اخلالگرانه', value: 'هبک-قطع دسترسی اخلالگری' },
			{ label: 'استفادهٔ نادرست از صفحهٔ بحث هنگام بسته بودن', value: 'بسته‌شده بدون دسترسی بحث-اعلان' },
			{ label: 'برای کمک به دانشنامه اینجا نیست', value: 'هبک-قطع دسترسی اینجا نه' },
			{ label: 'مطالب بدون منبع', value: 'هبک-قطع دسترسی مطالب بدون منبع' },
			{ label: 'خرابکاری', value: 'هبک-قطع دسترسی خرابکاری' },
			{ label: 'حساب ایجادشده برای خرابکاری', value: 'هبک-قطع دسترسی حساب خرابکار' }
		]
	},
	{
		label: 'دلایل بیشتر',
		list: [
			{ label: 'تبلیغات', value: 'هبک-قطع دسترسی هرزنگاری' },
		//	{ label: 'Arbitration enforcement', value: 'uw-aeblock' },
			{ label: 'دور زدن قطع دسترسی - آی‌پی', value: 'هبک-بستن دور زدن قطع دسترسی' },
			{ label: 'نقض وپ:زنده', value: 'هبک-قطع دسترسی زندگان' },
			{ label: 'نقض حق تکثیر', value: 'هبک-قطع دسترسی حق تکثیر' },
			{ label: 'ایجاد صفحه‌های نامفهوم', value: 'هبک-قطع دسترسی بی‌معنی' },
			{ label: 'مرتبط با پالایه', value: 'هبک-قطع دسترسی پالایه ویرایش' },
			{ label: 'جنگ ویرایشی', value: 'هبک-قطع دسترسی جنگ ویرایشی' },
			{ label: 'قطع دسترسی عمومی به‌همراه گرفتن دسترسی بحث', value: 'هبک-قطع دسترسی بحث' },
			{ label: 'آزار و اذیت', value: 'هبک-قطع دسترسی آزار' },
			{ label: 'تهدید قانونی', value: 'هبک-قطع دسترسی تهدید' },
			{ label: 'حمله شخصی یا آزار و اذیت', value: 'هبک-قطع دسترسی حمله شخصی' },
			{ label: 'احتمال به خطر افتادن حساب', value: 'هبک-بستن حساب به‌خطر افتاده' },
			{ label: 'حذف محتوا', value: 'هبک-قطع دسترسی حذف محتوا' },
			{ label: 'زاپاس‌بازی (حساب اصلی)', value: 'هبک-قطع دسترسی زاپاس' },
			{ label: 'زاپاس‌بازی (حساب زاپاس)', value: 'بستن زاپاس' },
			{ label: 'استفاده مشابه شبکه‌های اجتماعی', value: 'هبک-قطع دسترسی شبکه اجتماعی' },
			{ label: 'هرزنگاری', value: 'هبک-قطع دسترسی اسپم' },
			{ label: 'حساب ایجاد شده برای هرزنگاری/تبلیغات', value: 'هبک-بستن حساب هرزنگار' },
			{ label: 'ربات فاقد مجوز', value: 'هبک-قطع دسترسی ربات' },
			{ label: 'ویرایش در برابر دستمزد فاش‌نشده', value: 'هبک-بستن نام کاربری دستمزد ' },
			{ label: 'نقض قاعدهٔ سه‌برگردان', value: 'هبک-قطع دسترسی ۳ب' }
		]
	},
	{
		label: 'نقض سیاست نام کاربری',
		list: [
			{ label: 'نام کاربری ربات، قطع دسترسی نرم', value: 'هبک-بستن نام کاربری ربات' },
			{ label: 'نام کاربری ربات، قطع دسترسی سخت', value: 'هبک-بستن سخت نام ربات' },
			{ label: 'نام کاربری تبلیغاتی، قطع دسترسی سخت', value: 'هبک-قطع دسترسی نرم هرزنگاری' },
			{ label: 'نام کاربری تبلیغاتی، قطع دسترسی نرم', value: 'هبک-قطع دسترسی نرم نام کاربری' },
			{ label: 'نام کاربری مشابه، قطع دسترسی نرم', value: 'هبک-قطع دسترسی نام کاربری-تکراری' },
			{ label: 'نقض سیاست نام کاربری، قطع دسترسی نرم', value: 'هبک-قطع دسترسی نام کاربری' },
			{ label: 'نقض سیاست نام کاربری، قطع دسترسی سخت', value: 'هبک-بستن سخت نام کاربری' },
			{ label: 'جعل هویت با نام کاربری، قطع دسترسی سخت', value: 'هبک-بستن سخت نام کاربری-تکراری' },
			{ label: 'نام کاربری نمایندهٔ شخص سرشناس، قطع دسترسی نرم', value: 'بستن نام واقعی' },
			{ label: 'نام کاربری نمایندهٔ سازمان ناسودبر، قطع دسترسی نرم', value: 'هبک-قطع دسترسی جنبش' },
			{ label: 'نقض سیاست نام کاربری، حساب ایجادشده برای خرابکاری', value: 'هبک-بستن نام کاربری خرابکاری' }
		]
	},
	{
		label: 'دلیل‌های حاوی الگو',
		list: [
			{ label: 'پروکسی بسته شده', value: 'پروکسی باز' },
			{ label: 'قطع دسترسی بازرسی کاربر', value: 'قطع دسترسی بازرسی کاربر' },
			{ label: 'قطع دسترسی بازرسی کاربر-حساب کاربری', value: 'بندایش بازرسی کاربر-حساب کاربری' },
			{ label: 'قطع دسترسی بازرسی کاربر-کلی', value: 'قطع دسترسی بازرسی کاربر-کلی' },
			{ label: 'میزبانی وب‌سرور', value: 'میزبانی‌وب‌سرور' },
			{ label: 'قطع دسترسی پنهان‌گر', value: 'قطع دسترسی پنهان‌گر' },
			{ label: 'قطع دسترسی بازه آی‌پی', value: 'قطع دسترسی بازه آی‌پی' }, // Only for IP ranges, selected for non-/64 ranges in filtered_block_groups
			{ label: 'قطع دسترسی فهرست سیاه', value: 'بستن فهرست سیاه' },
			{ label: 'تور', value: 'تور' },
			{ label: 'میزبان وب بسته‌شده', value: 'میزبان وب بسته‌شده' },
			{ label: 'زامبی پراکسی', value: 'زامبی پراکسی' }
		]
	}
];

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


Twinkle.block.callback.filtered_block_groups = function twinkleblockCallbackFilteredBlockGroups(group, show_template) {
	return $.map(group, function(blockGroup) {
		var list = $.map(blockGroup.list, function(blockPreset) {
			switch (blockPreset.value) {
				case 'uw-talkrevoked':
					if (blockedUserName !== relevantUserName) {
						return;
					}
					break;
				case 'rangeblock':
					if (!Morebits.ip.isRange(relevantUserName)) {
						return;
					}
					blockPreset.selected = !Morebits.ip.get64(relevantUserName);
					break;
				case 'CheckUser block':
				case 'checkuserblock-account':
				case 'checkuserblock-wide':
					if (!Morebits.userIsInGroup('checkuser')) {
						return;
					}
					break;
				case 'oversightblock':
					if (!Morebits.userIsInGroup('suppress')) {
						return;
					}
					break;
				default:
					break;
			}

			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 form = e.target.form, key = form.preset.value;
	if (!key) {
		return;
	}

	Twinkle.block.callback.update_form(e, Twinkle.block.blockPresetsInfo[key]);
	if (form.template) {
		form.template.value = Twinkle.block.blockPresetsInfo[key].templateName || key;
		Twinkle.block.callback.change_template(e);
	} else {
		Morebits.quickForm.setElementVisibility(form.dstopic.parentNode, key === 'uw-aeblock' || key === 'uw-aepblock');
	}
};

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(' و ');

	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 + ' بھی دیکھیں';
	}
};

/* Localized [Removed; no DS in urwiki]
Twinkle.block.dsReason = '';
Twinkle.block.callback.toggle_ds_reason = function twinkleblockCallbackToggleDSReason() {
	var reason = this.form.reason.value.replace(
		new RegExp(' ?\\(\\[\\[' + Twinkle.block.dsReason + '\\]\\]\\)'), ''
	);

	Twinkle.block.dsinfo.then(function(dsinfo) {
		var sanctionCode = this.selectedIndex;
		var sanctionName = this.options[sanctionCode].label;
		Twinkle.block.dsReason = dsinfo[sanctionName].page;
		if (!this.value) {
			this.form.reason.value = reason;
		} else {
			this.form.reason.value = reason + ' ([[' + Twinkle.block.dsReason + ']])';
		}
	}.bind(this));
}; */

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.userIsBot || /bot\b/i.test(relevantUserName) || /روبہ$/.test(relevantUserName)) {
		data.autoblock = false;
	}

	$(form).find('[name=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 || '';
	}

	// Clear and/or set any partial page or namespace restrictions
	if (form.pagerestrictions) {
		var $pageSelect = $(form).find('[name=pagerestrictions]');
		var $namespaceSelect = $(form).find('[name=namespacerestrictions]');

		// Respect useInitialOptions by clearing data when switching presets
		// In practice, this will always clear, since no partial presets use it
		if (!data.useInitialOptions) {
			$pageSelect.val(null).trigger('change');
			$namespaceSelect.val(null).trigger('change');
		}

		// Add any preset options; in practice, just used for prior block settings
		if (data.restrictions) {
			if (data.restrictions.pages && !$pageSelect.val().length) {
				var pages = data.restrictions.pages.map(function(pr) {
					return pr.title;
				});
				// since page restrictions use an ajax source, we
				// short-circuit that and just add a new option
				pages.forEach(function(page) {
					if (!$pageSelect.find("option[value='" + $.escapeSelector(page) + "']").length) {
						var newOption = new Option(page, page, true, true);
						$pageSelect.append(newOption);
					}
				});
				$pageSelect.val($pageSelect.val().concat(pages)).trigger('change');
			}
			if (data.restrictions.namespaces) {
				$namespaceSelect.val($namespaceSelect.val().concat(data.restrictions.namespaces)).trigger('change');
			}
		}
	}
};

Twinkle.block.callback.change_template = function twinkleblockcallbackChangeTemplate(e) {
	var form = e.target.form, value = form.template.value, settings = Twinkle.block.blockPresetsInfo[value];

	var blockBox = $(form).find('[name=actiontype][value=block]').is(':checked');
	var partialBox = $(form).find('[name=actiontype][value=partial]').is(':checked');
	var templateBox = $(form).find('[name=actiontype][value=template]').is(':checked');

	// Block form is not present
	if (!blockBox) {
		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 = 'infinity';
		} 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);
		// Partial
		Morebits.quickForm.setElementVisibility(form.noemail_template.parentNode, partialBox);
		Morebits.quickForm.setElementVisibility(form.nocreate_template.parentNode, partialBox);
	} else if (templateBox) { // Only present if block && template forms both visible
		Morebits.quickForm.setElementVisibility(
			form.blank_duration.parentNode,
			!settings.indefinite && !settings.nonstandard
		);
	}

	Morebits.quickForm.setElementVisibility(form.dstopic.parentNode, value === 'uw-aeblock' || value === 'uw-aepblock');

	// Only particularly relevant if template form is present
	Morebits.quickForm.setElementVisibility(form.article.parentNode, settings && !!settings.pageParam);
	Morebits.quickForm.setElementVisibility(form.block_reason.parentNode, settings && !!settings.reasonParam);

	// Partial block
	Morebits.quickForm.setElementVisibility(form.area.parentNode, partialBox && !blockBox);

	form.root.previewer.closePreview();
};
Twinkle.block.prev_template_expiry = 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: Morebits.string.isInfinity(form.template_expiry ? form.template_expiry.value : form.expiry.value),
		reason: form.block_reason.value,
		template: form.template.value,
		dstopic: form.dstopic.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, 'تبادلۂ_خیال_صارف:' + relevantUserName); // 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 ((templateoptions.template !== 'uw-epblock' || $form.find('select[name="preset"]').val() !== 'uw-epblock') &&
					// Don't require confirmation if email harassment defaults are set
					!confirm('آپ صفحہ یا نام فضا میں ترمیم کاری کی اجازت کے ساتھ پابندی لگا رہے ہیں۔ کیا آپ واقعی ایسا کرنا چاہتے ہیں؟')) {
					return;
				}
			}
		}
		if (!blockoptions.expiry) {
			return alert('براہ کرم مدت اختتام درج کریں!');
		} else if (Morebits.string.isInfinity(blockoptions.expiry) && !Twinkle.block.isRegistered) {
			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 = relevantUserName;

		// 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).
		*/
		var query = {
			format: 'json',
			action: 'query',
			list: 'blocks|logevents',
			letype: 'block',
			lelimit: 1,
			letitle: 'صارف:' + blockoptions.user
		};
		// bkusers doesn't catch single IPs blocked as part of a range block
		if (mw.util.isIPAddress(blockoptions.user, true)) {
			query.bkip = blockoptions.user;
		} else {
			query.bkusers = blockoptions.user;
		}
		api.get(query).then(function(data) {
			var block = data.query.blocks[0];
			// As with the initial data fetch, if an IP is blocked
			// *and* rangeblocked, this would only grab whichever
			// block is more recent, which would likely mean a
			// mismatch.  However, if the rangeblock is updated
			// while filling out the form, this won't detect that,
			// but that's probably fine.
			if (data.query.blocks.length > 1 && block.user !== relevantUserName) {
				block = data.query.blocks[1];
			}
			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 = 'صارف ' + blockoptions.user + ' کی پابندی کی کیفیت تبدیل ہو گئی۔ ';
				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 += logActionsTranslations[logevents.action] + ' بذریعہ ' + logevents.user + logExpiry +
					' بوجہ «' + logevents.comment + '»۔ کیا آپ اپنی ذاتی ترتیبات استعمال کرنا چاہتے ہیں؟';

				if (!confirm(message)) {
					Morebits.status.info('پابندی لگائی جا رہی ہے', 'صارف کی درخواست پر کارروائی کو روک دیا گیا');
					return;
				}
				blockoptions.reblock = 1; // Writing over a block will fail otherwise
			}

			// execute block
			blockoptions.tags = Twinkle.changeTags;
			blockoptions.token = mw.user.tokens.get('csrfToken');
			var mbApi = new Morebits.wiki.api('پابندی لگائی جا رہی ہے', blockoptions, function() {
				statusElement.info('مکمل');
				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) {
	// Use wgRelevantUserName to ensure the block template goes to a single IP and not to the
	// "talk page" of an IP range (which does not exist)
	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 = 'اقدامات مکمل، چند سیکنڈ میں صارف کا تبادلۂ خیال صفحہ لوڈ ہوگا';

	var wikipedia_page = new Morebits.wiki.page(userTalkPage, 'صارف کے تبادلۂ خیال صفحہ میں ترمیم');
	wikipedia_page.setCallbackParameters(params);
	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 += 'جا:' + params.template;
		if (params.article && settings.pageParam) {
			text += '|page=' + params.article;
		}
		if (params.dstopic) {
			text += '|topic=' + params.dstopic;
		}

		if (!/te?mp|^\s*$|min/.exec(params.expiry)) {
			if (params.indefinite) {
				text += '|indef=yes';
			} else if (!params.blank_duration && !new Morebits.date(params.expiry).isValid()) {
				// Block template wants a duration, not date
				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) + ')';
				}
			} 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 params = pageobj.getCallbackParameters(),
		date = new Morebits.date(pageobj.getLoadTime()),
		messageData = params.messageData,
		text;

	params.indefinite = Morebits.string.isInfinity(params.expiry);

	if (Twinkle.getPref('blankTalkpageOnIndefBlock') && params.template !== 'uw-lblock' && params.indefinite) {
		Morebits.status.info('اطلاع', 'ترجیحات کے مطابق تبادلۂ خیال صفحہ کو خالی کر کے رواں مہینے کے لیے نئی سرخی لگائی جا رہی ہے');
		text = date.monthHeader() + '\n';
	} else {
		text = pageobj.getPageText();

		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';
		}

		if (!dateHeaderRegexResult || dateHeaderRegexResult.index !== lastHeaderIndex) {
			Morebits.status.info('اطلاع', 'چونکہ رواں مہینے کی کوئی سرخی نہیں ملی لہذا اس مہینے کے عنوان سے نیا قطعہ بنایا جائے گا');
			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 + ']] پر';
	}
	summary += '۔';

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

Twinkle.addInitCallback(Twinkle.block, 'block');
})(jQuery);


// </nowiki>