MediaWiki:Gadget-twinkle.js

De la Wikipedia, enciclopedia liberă

Notă: După salvare, trebuie să treceți peste cache-ul browser-ului pentru a vedea modificările.

  • Mozilla, Google Chrome, Safari, Konqueror: țineți apăsat Shift în timp ce apăsați butonul Reload (sau apăsați Ctrl-Shift-R).
  • Internet Explorer: apăsați Ctrl-F5.
  • Opera: apăsați F5.
/**
 * +-------------------------------------------------------------------------+
 * |                  === WARNING: GLOBAL GADGET FILE ===                    |
 * |                Changes to this page affect many users.                  |
 * |           Please discuss changes at [[WT:TW]] before editing.           |
 * +-------------------------------------------------------------------------+
 *
 * Imported from github [https://github.com/azatoth/twinkle]
 * To update this script from github, you must have a local repository set up. Then
 * follow the instructions at [https://github.com/azatoth/twinkle/blob/master/README.md].
 *
 * ----------
 *
 * This is AzaToth's Twinkle. See [[WP:TW]].
 * It needs a better header comment than this one.
 */

//<nowiki>
( function ( window, document, $, undefined ) {
var Twinkle = {};
window.Twinkle = Twinkle;  // allow global access

// for use by custom modules (normally empty)
Twinkle.initCallbacks = [];
Twinkle.addInitCallback = function twinkleAddInitCallback(func) {
	Twinkle.initCallbacks.push(func);
};

Twinkle.defaultConfig = {};
/**
 * Twinkle.defaultConfig.twinkle and Twinkle.defaultConfig.friendly
 *
 * This holds the default set of preferences used by Twinkle. (The |friendly| object holds preferences stored in the FriendlyConfig object.)
 * It is important that all new preferences added here, especially admin-only ones, are also added to
 * |Twinkle.config.sections| in twinkleconfig.js, so they are configurable via the Twinkle preferences panel.
 * For help on the actual preferences, see the comments in twinkleconfig.js.
 */
Twinkle.defaultConfig.twinkle = {
	 // General
	summaryAd: " ([[WP:TW|TW]])",
	deletionSummaryAd: " ([[WP:TW|TW]])",
	protectionSummaryAd: " ([[WP:TW|TW]])",
	userTalkPageMode: "window",
	dialogLargeFont: false,
	 // Fluff (revert and rollback)
	openTalkPage: [ "agf", "norm", "vand" ],
	openTalkPageOnAutoRevert: false,
	markRevertedPagesAsMinor: [ "vand" ],
	watchRevertedPages: [ "agf", "norm", "vand", "torev" ],
	offerReasonOnNormalRevert: true,
	confirmOnFluff: false,
	showRollbackLinks: [ "diff", "others" ],
	 // DI (twinkleimage)
	notifyUserOnDeli: true,
	deliWatchPage: "default",
	deliWatchUser: "default",
	 // CSD
	speedyPromptOnG7: false,
	watchSpeedyPages: [ "g3", "g5", "g10", "g11", "g12" ],
	markSpeedyPagesAsPatrolled: true,
	// these next two should probably be identical by default
	notifyUserOnSpeedyDeletionNomination:    [ "db", "g1", "g2", "g3", "g4", "g10", "g11", "g12", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11", "f1", "f2", "f3", "f7", "f9", "f10", "u3", "t2", "t3", "p1", "p2" ],
	welcomeUserOnSpeedyDeletionNotification: [ "db", "g1", "g2", "g3", "g4", "g10", "g11", "g12", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11", "f1", "f2", "f3", "f7", "f9", "f10", "u3", "t2", "t3", "p1", "p2" ],
	promptForSpeedyDeletionSummary: [ "db", "g1", "g2", "g3", "g4", "g6", "g7", "g8", "g10", "g11", "g12", "a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11", "f2", "f4", "f7", "f8", "f10", "t2", "t3", "p1", "p2" ],
	openUserTalkPageOnSpeedyDelete: [ "db", "g1", "g2", "g3", "g4", "g5", "g10", "g11", "g12", "a1", "a3", "a7", "a9", "a10", "a11", "f3", "f7", "f9", "u3", "t2", "p1" ],
	deleteTalkPageOnDelete: false,
	deleteSysopDefaultToTag: false,
	speedyWindowHeight: 500,
	speedyWindowWidth: 800,
	logSpeedyNominations: false,
	speedyLogPageName: "CSD log",
	noLogOnSpeedyNomination: [ "u1" ],
	 // Unlink
	unlinkNamespaces: [ "0", "100" ],
	 // Warn
	defaultWarningGroup: "1",
	showSharedIPNotice: true,
	watchWarnings: true,
	blankTalkpageOnIndefBlock: false,
	 // XfD
	xfdWatchDiscussion: "default",
	xfdWatchList: "no",
	xfdWatchPage: "default",
	xfdWatchUser: "default",
	 // Hidden preferences
	revertMaxRevisions: 50,
	batchdeleteChunks: 50,
	batchDeleteMinCutOff: 5,
	batchMax: 5000,
	batchProtectChunks: 50,
	batchProtectMinCutOff: 5,
	batchundeleteChunks: 50,
	batchUndeleteMinCutOff: 5,
	deliChunks: 500,
	deliMax: 5000,
};

// now some skin dependent config.
switch (mw.config.get('skin')) {
	case 'vector':
	case 'vector-2022':
		Twinkle.defaultConfig.twinkle.portletArea = 'right-navigation';
		Twinkle.defaultConfig.twinkle.portletId = 'p-twinkle';
		Twinkle.defaultConfig.twinkle.portletName = 'TW';
		Twinkle.defaultConfig.twinkle.portletType = 'menu';
		Twinkle.defaultConfig.twinkle.portletNext = 'p-search';
		break;
	case 'timeless':
		Twinkle.defaultConfig.twinkle.portletArea = '#page-tools .sidebar-inner';
		Twinkle.defaultConfig.twinkle.portletId = 'p-twinkle';
		Twinkle.defaultConfig.twinkle.portletName = 'Twinkle';
		Twinkle.defaultConfig.twinkle.portletType = null;
		Twinkle.defaultConfig.twinkle.portletNext = 'p-userpagetools';
		break;
	default:
		Twinkle.defaultConfig.twinkle.portletArea = null;
		Twinkle.defaultConfig.twinkle.portletId = 'p-cactions';
		Twinkle.defaultConfig.twinkle.portletName = null;
		Twinkle.defaultConfig.twinkle.portletType = null;
		Twinkle.defaultConfig.twinkle.portletNext = null;
}




Twinkle.defaultConfig.friendly = {
	 // Tag
	groupByDefault: true,
	watchTaggedPages: true,
	markTaggedPagesAsMinor: false,
	markTaggedPagesAsPatrolled: true,
	customTagList: [],
	 // Welcome
	topWelcomes: false,
	watchWelcomes: true,
	welcomeHeading: "Welcome",
	insertHeadings: true,
	insertUsername: true,
	insertSignature: true,  // sign welcome templates, where appropriate
	markWelcomesAsMinor: true,
	quickWelcomeMode: "norm",
	quickWelcomeTemplate: "welcome",
	maskTemplateInSummary: true,
	customWelcomeList: [],
	 // Talkback
	markTalkbackAsMinor: true,
	insertTalkbackSignature: true,  // always sign talkback templates
	talkbackHeading: "Răspuns",
	adminNoticeHeading: "Notificare",
	 // Shared
	markSharedIPAsMinor: true
};

Twinkle.getPref = function twinkleGetPref(name) {
	var result;
	if (Twinkle.prefs && typeof(Twinkle.prefs) === "object" && typeof(Twinkle.prefs.twinkle) === "object") {
		// look in Twinkle.prefs (twinkleoptions.js)
		result = Twinkle.prefs.twinkle[name];
	} else if (window.TwinkleConfig && typeof(window.TwinkleConfig) === "object") {
		// look in TwinkleConfig
		result = window.TwinkleConfig[name];
	}

	if (typeof(result) === "undefined") {
		return Twinkle.defaultConfig.twinkle[name];
	}
	return result;
};

Twinkle.getFriendlyPref = function twinkleGetFriendlyPref(name) {
	var result;
	if (Twinkle.prefs && typeof(Twinkle.prefs) === "object" && typeof(Twinkle.prefs.friendly) === "object") {
		// look in Twinkle.prefs (twinkleoptions.js)
		result = Twinkle.prefs.friendly[name];
	} else if (window.FriendlyConfig && typeof(window.FriendlyConfig) === "object") {
		// look in FriendlyConfig
		result = window.FriendlyConfig[name];
	}

	if (typeof(result) === "undefined") {
		return Twinkle.defaultConfig.friendly[name];
	}
	return result;
};



/**
 * **************** twAddPortlet() ****************
 *
 * Adds a portlet menu to one of the navigation areas on the page.
 * This is necessarily quite a hack since skins, navigation areas, and
 * portlet menu types all work slightly different.
 *
 * Available navigation areas depend on the skin used.
 * Monobook:
 *  "column-one", outer div class "portlet", inner div class "pBody". Existing portlets: "p-cactions", "p-personal", "p-logo", "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
 *  Special layout of p-cactions and p-personal through specialized styles.
 * Vector:
 *  "mw-panel", outer div class "portal", inner div class "body". Existing portlets/elements: "p-logo", "p-navigation", "p-interaction", "p-tb", "p-coll-print_export"
 *  "left-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-namespaces", "p-variants" (menu)
 *  "right-navigation", outer div class "vectorTabs" or "vectorMenu", inner div class "" or "menu". Existing portlets: "p-views", "p-cactions" (menu), "p-search"
 *  Special layout of p-personal portlet (part of "head") through specialized styles.
 * Modern:
 *  "mw_contentwrapper" (top nav), outer div class "portlet", inner div class "pBody". Existing portlets or elements: "p-cactions", "mw_content"
 *  "mw_portlets" (sidebar), outer div class "portlet", inner div class "pBody". Existing portlets: "p-navigation", "p-search", "p-interaction", "p-tb", "p-coll-print_export"
 *
 * @param String navigation -- id of the target navigation area (skin dependant, on vector either of "left-navigation", "right-navigation", or "mw-panel")
 * @param String id -- id of the portlet menu to create, preferably start with "p-".
 * @param String text -- name of the portlet menu to create. Visibility depends on the class used.
 * @param String type -- type of portlet. Currently only used for the vector non-sidebar portlets, pass "menu" to make this portlet a drop down menu.
 * @param Node nextnodeid -- the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end.
 *
 * @return Node -- the DOM node of the new item (a DIV element) or null
 */
function twAddPortlet( navigation, id, text, type, nextnodeid )
{
	// sanity checks, and get required DOM nodes
	var root = document.getElementById(navigation);
	if (!root) {
		return null;
	}

	var item = document.getElementById(id);
	if (item) {
		if (item.parentNode && item.parentNode === root) {
			return item;
		}
		return null;
	}

	var nextnode;
	if (nextnodeid) {
		nextnode = document.getElementById(nextnodeid);
	}

	// verify/normalize input
	var skin = mw.config.get('skin');
	if ((skin !== 'vector' && skin !== 'vector-2022') || (navigation !== 'left-navigation' && navigation !== 'right-navigation')) {
		type = null; // menu supported only in vector's #left-navigation & #right-navigation
	} else {
		type = 'menu'
	}
	var outerDivClass;
	var innerDivClass;
	switch (skin) {
		case 'vector':
		case 'vector-2022':
			if (navigation !== 'portal' && navigation !== 'left-navigation' && navigation !== 'right-navigation') {
				navigation = 'mw-panel';
			}
			outerDivClass = 'mw-portlet vector-menu vector-menu-' + (navigation === 'mw-panel' ? 'portal' : type === 'menu' ? 'dropdown vector-dropdown vector-dropdown vector-menu-dropdown-noicon' : 'tabs');
			innerDivClass = 'vector-menu-content vector-dropdown-content';
			break;
		case 'modern':
			if (navigation !== 'mw_portlets' && navigation !== 'mw_contentwrapper') {
				navigation = 'mw_portlets';
			}
			outerDivClass = 'portlet';
			innerDivClass = 'pBody';
			break;
		default:
			navigation = 'column-one';
			outerDivClass = 'portlet';
			innerDivClass = 'pBody';
			break;
	}

	// Build the DOM elements.
	var outerDiv, heading;
	
	if (skin === 'vector-2022') {
		outerDiv = document.createElement('div');
		heading = document.createElement('label');
	} else {
		outerDiv = document.createElement('nav');
		heading = document.createElement('h3');
	}
	outerDiv.setAttribute('aria-labelledby', id + '-label');
	// Vector getting vector-menu-empty FIXME TODO
	outerDiv.className = outerDivClass + ' emptyPortlet';
	outerDiv.id = id;
	if (nextnode && nextnode.parentNode === root) {
		root.insertBefore(outerDiv, nextnode);
	} else {
		root.appendChild(outerDiv);
	}

	heading.id = id + '-label';
	var ul = document.createElement('ul');

	if (skin === 'vector' || skin === 'vector-2022') {
		ul.className = 'vector-menu-content-list';
		heading.className = 'vector-menu-heading vector-dropdown-label';
		// add invisible checkbox to keep menu open when clicked
		// similar to the p-cactions ("More") menu
		if (outerDivClass.indexOf('vector-menu-dropdown') !== -1) {
			var chkbox = document.createElement('input');
			chkbox.id = id + '-dropdown-checkbox';
			chkbox.className = 'vector-menu-checkbox vector-dropdown-checkbox';
			chkbox.setAttribute('type', 'checkbox');
			chkbox.setAttribute('aria-labelledby', id + '-label');
			outerDiv.appendChild(chkbox);

			var span = document.createElement('span');
			span.appendChild(document.createTextNode(text));
			heading.appendChild(span);

			var a = document.createElement('a');
			a.href = '#';

			$(a).click(function(e) {
				e.preventDefault();
                                if (!Twinkle.userAuthorized) {
                                        alert('Sorry, your account is too new to use Twinkle.');
                                };
			});

			heading.appendChild(a);
		}

		outerDiv.appendChild(heading);
		ul.className = 'menu vector-menu-content-list';  // remove menu after 1.35-wmf.37 goes live
	} else {
		heading.appendChild(document.createTextNode(text));
		outerDiv.appendChild(heading);
	}

	if (innerDivClass) {
		var innerDiv = document.createElement('div');
		innerDiv.className = innerDivClass;
		innerDiv.appendChild(ul);
		outerDiv.appendChild(innerDiv);
	} else {
		outerDiv.appendChild(ul);
	}


	return outerDiv;

};

/**
 * **************** twAddPortletLink() ****************
 * Builds a portlet menu if it doesn't exist yet, and add the portlet link.
 */
function twAddPortletLink( task, text, id, tooltip )
{
	if ( Twinkle.getPref("portletArea") !== null ) {
		twAddPortlet( Twinkle.getPref( "portletArea" ), Twinkle.getPref( "portletId" ), Twinkle.getPref( "portletName" ), Twinkle.getPref( "portletType" ), Twinkle.getPref( "portletNext" ));
	}

	var link = mw.util.addPortletLink( Twinkle.getPref( "portletId" ), typeof task === "string" ? task : "#", text, id, tooltip );
	$('.client-js .skin-vector #p-cactions').css('margin-right', 'initial');
	if (typeof task === 'function') {
		$(link).click(function (ev) {
			task();
			ev.preventDefault();
		});
	}
	if ($.collapsibleTabs) {
		$.collapsibleTabs.handleResize();
	}
	return link;
}

// check if account is experienced enough for more advanced functions
var twinkleUserAuthorized = Morebits.userIsInGroup( 'autoconfirmed' ) || Morebits.userIsInGroup( 'confirmed' );

/*
 ****************************************
 *** friendlyshared.js: Shared IP tagging module
 ****************************************
 * Mode of invocation:     Tab ("Shared")
 * Active on:              Existing IP user talk pages
 * Config directives in:   FriendlyConfig
 */

Twinkle.shared = function friendlyshared() {
	if( mw.config.get('wgNamespaceNumber') === 3 && mw.util.isIPAddress(mw.config.get('wgTitle')) ) {
		var username = mw.config.get('wgTitle').split( '/' )[0].replace( /\"/, "\\\""); // only first part before any slashes
		twAddPortletLink(function() { Twinkle.shared.callback(username); }, "Shared IP", "friendly-shared", "Shared IP tagging");
	}
};

Twinkle.shared.callback = function friendlysharedCallback( uid ) {
	var Window = new Morebits.simpleWindow( 600, 400 );
	Window.setTitle( "Shared IP address tagging" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#shared" );

	var form = new Morebits.quickForm( Twinkle.shared.callback.evaluate );

	form.append( { type:'header', label:'Shared IP address templates' } );
	form.append( { type: 'radio', name: 'shared', list: Twinkle.shared.standardList,
		event: function( e ) {
			Twinkle.shared.callback.change_shared( e );
			e.stopPropagation();
		} } );

	var org = form.append( { type:'field', label:'Fill in IP address owner/operator, hostname and contact information (if applicable) and hit \"Submit\"' } );
	org.append( {
			type: 'input',
			name: 'organization',
			label: 'Organization name',
			disabled: true,
			tooltip: 'Some of these templates support an optional parameter for the organization name that owns/operates the IP address.  The organization name can be entered here for those templates, including wikimarkup if necessary.'
		}
	);
	org.append( {
			type: 'input',
			name: 'host',
			label: 'Host name (optional)',
			disabled: true,
			tooltip: 'These templates support an optional parameter for the host name.  The host name (for example, proxy.example.com) can be entered here and will be linked by the template.'
		}
	);
	org.append( {
			type: 'input',
			name: 'contact',
			label: 'Contact information (only if requested)',
			disabled: true,
			tooltip: 'Some of these templates support an optional parameter for the organization\'s contact information.  Use this parameter only if the organization has specifically request that it be added.  This contact information can be entered here for those templates, including wikimarkup if necessary.'
		}
	);
	
	form.append( { type:'submit' } );

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

Twinkle.shared.standardList = [
	{
		label: '{{shared IP}}: standard shared IP address template',
		value: 'shared IP',
		tooltip: 'IP user talk page template that shows helpful information to IP users and those wishing to warn, block or ban them'
	},
	{ 
		label: '{{shared IP edu}}: shared IP address template modified for educational institutions',
		value: 'shared IP edu'
	},
	{
		label: '{{shared IP corp}}: shared IP address template modified for businesses',
		value: 'shared IP corp'
	},
	{
		label: '{{shared IP public}}: shared IP address template modified for public terminals',
		value: 'shared IP public'
	},
	{
		label: '{{shared IP gov}}: shared IP address template modified for government agencies or facilities',
		value: 'shared IP gov'
	},
	{
		label: '{{dynamicIP}}: shared IP address template modified for organizations with dynamic addressing',
		value: 'dynamicIP'
	},
	{ 
		label: '{{ISP}}: shared IP address template modified for ISP organizations (specifically proxies)',
		value: 'ISP'
	},
	{ 
		label: '{{mobileIP}}: shared IP address template modified for mobile phone companies and their customers',
		value: 'mobileIP'
	}
];

Twinkle.shared.callback.change_shared = function friendlytagCallbackChangeShared(e) {
	if( e.target.value === 'shared IP edu' ) {
		e.target.form.contact.disabled = false;
	} else {
		e.target.form.contact.disabled = true;
	}
	e.target.form.organization.disabled=false;
	e.target.form.host.disabled=false;
};

Twinkle.shared.callbacks = {
	main: function( pageobj ) {
		var params = pageobj.getCallbackParameters();
		var pageText = pageobj.getPageText();
		var found = false;
		var text = '{{';

		for( var i=0; i < Twinkle.shared.standardList.length; i++ ) {
			tagRe = new RegExp( '(\\{\\{' + Twinkle.shared.standardList[i].value + '(\\||\\}\\}))', 'im' );
			if( tagRe.exec( pageText ) ) {
				Morebits.status.warn( 'Info', 'Găsit {{' + Twinkle.shared.standardList[i].value + '}} pe pagina de discuție a utilizatorului...renunț' );
				found = true;
			}
		}

		if( found ) {
			return;
		}

		Morebits.status.info( 'Info', 'Adaug formatul de adresă IP partajată în pagina sa de discuție.' );
		text += params.value + '|' + params.organization;
		if( params.value === 'shared IP edu' && params.contact !== '') {
			text += '|' + params.contact;
		}
		if( params.host !== '' ) {
			text += '|host=' + params.host;
		}
		text += '}}\n\n';

		var summaryText = 'Adăugat formatul {{[[Template:' + params.value + '|' + params.value + ']]}}.';
		pageobj.setPageText(text + pageText);
		pageobj.setEditSummary(summaryText + Twinkle.getPref('summaryAd'));
		pageobj.setMinorEdit(Twinkle.getFriendlyPref('markSharedIPAsMinor'));
		pageobj.setCreateOption('recreate');
		pageobj.save();
	}
};

Twinkle.shared.callback.evaluate = function friendlysharedCallbackEvaluate(e) {
	var shared = e.target.getChecked( 'shared' );
	if( !shared || shared.length <= 0 ) {
		alert( 'You must select a shared IP address template to use!' );
		return;
	}
	
	var value = shared[0];
	
	if( e.target.organization.value === '') {
		alert( 'You must input an organization for the {{' + value + '}} template!' );
		return;
	}
	
	var params = {
		value: value,
		organization: e.target.organization.value,
		host: e.target.host.value,
		contact: e.target.contact.value
	};

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( e.target );

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Etichetare terminată, pagina va fi reîncărcată în câteva secunde";

	var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Modificarea paginii de discuție a utilizatorului");
	wikipedia_page.setFollowRedirect(true);
	wikipedia_page.setCallbackParameters(params);
	wikipedia_page.load(Twinkle.shared.callbacks.main);
};

/*
 ****************************************
 *** friendlytag.js: Tag module
 ****************************************
 * Mode of invocation:     Tab ("Tag")
 * Active on:              Existing articles; file pages with a corresponding file
 *                         which is local (not on Commons); all redirects
 * Config directives in:   FriendlyConfig
 */

Twinkle.tag = function friendlytag() {
	// redirect tagging
	var username = mw.config.get('wgTitle').split( '/' )[0].replace( /\"/, "\\\""); // only first part before any slashes
	if( Morebits.wiki.isPageRedirect() ) {
		Twinkle.tag.mode = 'redirect';
		twAddPortletLink(function(){ Twinkle.tag.callback(username); }, "Etichetă", "friendly-tag", "Etichetare redirect");
	}
	// file tagging
	else if( mw.config.get('wgNamespaceNumber') === 6 && !document.getElementById("mw-sharedupload") && document.getElementById("mw-imagepage-section-filehistory") ) {
		Twinkle.tag.mode = 'file';
		twAddPortletLink(function(){ Twinkle.tag.callback(username); }, "Etichetă", "friendly-tag", "Adaugă etichete de întreținere la fișier");
	}
	// article tagging
	else if( mw.config.get('wgNamespaceNumber') === 0 && mw.config.get('wgCurRevisionId') ) {
		Twinkle.tag.mode = 'article';
		twAddPortletLink(function(){ Twinkle.tag.callback(username); }, "Etichetă", "friendly-tag", "Adaugă etichete de întreținere la articol");
	} else if (/Andrei.Stroe/.test(mw.config.get('wgPageName'))) {
		Twinkle.tag.mode = 'article';
		twAddPortletLink(function(){ Twinkle.tag.callback(username); }, "Etichetă", "friendly-tag", "Adaugă etichete de întreținere la articol");
	}
};

Twinkle.tag.callback = function friendlytagCallback( uid ) {
	var Window = new Morebits.simpleWindow( 630, 400 );
	Window.setScriptName( "Twinkle" );
	// anyone got a good policy/guideline/info page/instructional page link??
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#tag" );

	var form = new Morebits.quickForm( Twinkle.tag.callback.evaluate );

	switch( Twinkle.tag.mode ) {
		case 'article':
			Window.setTitle( "Etichetare articol" );

			form.append( {
					type: 'checkbox',
					list: [
						{
							label: 'Grupează în {{probleme}} dacă e posibil',
							value: 'group',
							name: 'group',
							tooltip: 'Dacă aplicați mai mult de două etichete suportate de {{probleme}} și această casetă este bifată, toate etichetele suportate vor fi grupate într-un singur format {{probleme}}.',
							checked: Twinkle.getFriendlyPref('groupByDefault')
						}
					]
				}
			);

			form.append( { type:'header', label:'Formate de întreținere' } );
			form.append( { type:'checkbox', name: 'maintenance', list: Twinkle.tag.maintenanceList } );

			form.append( { type:'header', label:'Formate pentru probleme' } );
			form.append( { type:'checkbox', name: 'problem', list: Twinkle.tag.problemList } );

			form.append( { type:'header', label:'Formate de notificare' } );
			form.append( { type:'checkbox', name: 'notice', list: Twinkle.tag.noticeList } );

			if( Twinkle.getFriendlyPref('customTagList').length ) {
				form.append( { type:'header', label:'Custom templates' } );
				form.append( { type: 'checkbox', name: 'custom', list: Twinkle.getFriendlyPref('customTagList') } );
			}
			break;

		case 'file':
			Window.setTitle( "Etichetarea fișierelor" );

			// TODO: perhaps add custom tags TO list of checkboxes

			form.append({ type: 'header', label: 'Probleme de licențiere și proveniență' });
			form.append({ type: 'checkbox', name: 'imageTags', list: Twinkle.tag.file.licenseList } );

			form.append({ type: 'header', label: 'Etichete de curățenie' } );
			form.append({ type: 'checkbox', name: 'imageTags', list: Twinkle.tag.file.cleanupList } );

			form.append({ type: 'header', label: 'Etichete de calitate' } );
			form.append({ type: 'checkbox', name: 'imageTags', list: Twinkle.tag.file.qualityList } );

			form.append({ type: 'header', label: 'Etichete legate de Wikimedia Commons' });
			form.append({ type: 'checkbox', name: 'imageTags', list: Twinkle.tag.file.commonsList } );

			form.append({ type: 'header', label: 'Etichete de înlocuire' });
			form.append({ type: 'checkbox', name: 'imageTags', list: Twinkle.tag.file.replacementList } );
			break;

		case 'redirect':
			Window.setTitle( "Etichetarea redirecționărilor" );

			form.append({ type: 'header', label:'Formate de ortografie, gramatică și majuscule' });
			form.append({ type: 'checkbox', name: 'spelling', list: Twinkle.tag.spellingList });

			form.append({ type: 'header', label:'Formate referitoare la nume alternative' });
			form.append({ type: 'checkbox', name: 'alternative', list: Twinkle.tag.alternativeList });

			form.append({ type: 'header', label:'Diverse formate administrative' });
			form.append({ type: 'checkbox', name: 'administrative', list: Twinkle.tag.administrativeList });
			break;

		default:
			alert("Twinkle.tag: Mod necunoscut: " + Twinkle.tag.mode);
			break;
	}

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

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

// Tags for ARTICLES start here

Twinkle.tag.maintenanceList = [	{
		label: '\{\{ajutor\}\}: articolul are nevoie de ajutor',
		value: 'ajutor'
	},
	{
		label: '\{\{curățenie\}\}: articolul are nevoie de curățenie',
		value: 'curățenie'
	},
	{
		label: '\{\{wikizare\}\}: articolul trebuie pus în formatul standard',
		value: 'wikizare'
	},
	{
		label: '\{\{necategorizate\}\}: articolul este inclus în nicio categorie sau în foarte puține',
		value: 'necategorizate'
	},
	{
		label: '\{\{detradus\}\}: articolul este scris într-o limbă străină',
		value: 'detradus'
	},
	{
		label: '\{\{extinde\}\}: acest articol trebuie extins',
		value: 'extinde'
	},
	{
		label: '\{\{popcat\}\}: această categorie trebuie populată',
		value: 'popcat'
	},
	{
		label: '\{\{punct de vedere mondial\}\}: articolul nu exprimă punctul de vedere mondial asupra subiectului',
		value: 'punct de vedere mondial' 
	},
	{
		label: '\{\{articol neverificat\}\}: acest articol trebuie verificat de către un editor',
		value: 'articol neverificat'
	},
	{
		label: '\{\{verificare\}\}: acest articol necesită o verificare',
		value: 'verificare'
	},
	{
		label: '\{\{divide\}\}: acest articol trebuie divizat în două sau mai multe articole',
		value: 'divide'
	},
	{
		label: '\{\{orfan\}\}: sunt foarte puține articole (sau chiar niciunul) care se leagă de acesta',
		value: 'orfan'
	},
	{
		label: '\{\{fără introducere\}\}: acest articol nu are introducere cu explicația scurtă a subiectului',
		value: 'fără introducere'
	},
	{
		label: '\{\{interlingual\}\}: acest articol are nevoie de adăugarea unor legături interlinguale',
		value: 'interlingual'
	},
	{
		label: '\{\{note de subsol\}\}: sursele articolului sunt neclare deoarece îi lipsesc notele de subsol.',
		value: 'note de subsol'
	},
	{
		label: '\{\{ton nepotrivit\}\}: tonul acestui articol sau al acestei secțiuni este nepotrivit pentru o enciclopedie',
		value: 'ton nepotrivit' 
	},
	{
		label: '\{\{diacritice\}\}: acest articol este scris parțial sau în întregime fără diacritice',
		value: 'diacritice' 
	},
	{
		label: '\{\{ortografie\}\}: acest articol conține greșeli de ortografie și/sau de punctuație.',
		value: 'ortografie' 
	},
	{
		label: '\{\{de corectat\}\}: acest articol conține erori de ortografie, folosește o exprimare alambicată sau stâlcește limba română',
		value: 'de corectat' 
	},
	{
		label: '\{\{ghilimele\}\}: acest articol conține ghilimele englezești, ce trebuiesc înlocuite cu cele românești',
		value: 'ghilimele' 
	},
	{
		label: '\{\{traducere automată\}\}: acest articol pare a conține text neinteligibil produs de o unealtă de traducere automată',
		value: 'traducere automată' 
	},
	{
		label: '\{\{listă\}\}: acest articol este scris sub formă de listă și trebuie reformulat sub formă de fraze cursive',
		value: 'listă' 
	},
	{
		label: '\{\{citate în exces\}\}: acest articol abuzează de citate, care trebuie utilizate doar în condițiile comentariului relevant',
		value: 'citate în exces' 
	},
	{
		label: '\{\{de tradus în alte limbi\}\}: acest articol este scris în limba română și trebuie tradus în alte limbi',
		value: 'de tradus în alte limbi' 
	},
	{
		label: '\{\{curățenie-simple legături web\}\}: acest articol își dă referințele ca simple legături web',
		value: 'curățenie-simple legături web'
	},
	{
		label: '\{\{independența surselor\}\}: acest articol citează surse îndeaproape asociate subiectului',
		value: 'independența surselor'
	}
];


Twinkle.tag.problemList = [	{
		label: '\{\{acuratețe\}\}: acuratețea acestui articol sau a acestei secțiuni este disputată. Necesită o justificare în pagina de discuții.',
		value: 'acuratețe'
	},
	{
		label: '\{\{copyvio|url=\}\}: această pagină este suspectă de violarea drepturilor de autor',
		value: 'copyvio'
	},
	{
		label: '\{\{referințe\}\}: acest articol sau această secțiune are bibliografia incompletă sau inexistentă',
		value: 'referințe'
	},
	{
		label: '\{\{legături externe\}\}: cel puțin o parte din aceste legături externe nu îndeplinesc condițiile de includere',
		value: 'legături externe'
	},
	{
		label: '\{\{original\}\}: acest articol pare să conțină cercetare originală',
		value: 'original'
	},
	{
		label: '\{\{PDVN\}\}: punctul de vedere neutru al acestui articol este disputat. Necesită o justificare în pagina de discuții.',
		value: 'PDVN'
	},
	{
		label: '\{\{notabilitate\}\}: din textul acestui articol nu rezultă caracterul notabil al subiectului',
		value: 'notabilitate'
	},
	{
		label: '\{\{neenciclopedic\}\}: conținutul sau subiectul acestui articol este privit de unii editori ca fiind neenciclopedic. Necesită o justificare în pagina de discuții.',
		value: 'neenciclopedic',
	},
	{
		label: '\{\{toponimie\}\}: acest articol se confruntă cu probleme de toponimie pe bază lingvistică. Necesită o justificare în pagina de discuții.',
		value: 'toponimie'
	},
	{
		label: '\{\{conținut\}\}: relevanța unor informații din acest articol este disputată. Necesită o justificare în pagina de discuții.',
		value: 'conținut'
	}
];

Twinkle.tag.noticeList = [
	{
		label: '\{\{dezvoltare\}\}: la această pagină sau secțiune se lucrează în prezent',
		value: 'dezvoltare',
	},
	{
		label: '\{\{modific acum\}\}: la acest articol se lucrează în acest moment, posibil cu o aplicație externă',
		value: 'modific acum',
	},
	{
		label: '\{\{expert\}\}: acest articol are nevoie de atenția unui expert în domeniu',
		value: 'expert' },
	{
		label: '\{\{în desfășurare\}\}: acest articol sau secțiune este de actualitate',
		value: 'în desfășurare',
	},
	{
		label: '\{\{titluincorect|Titlul corect\}\}: forma corectă a titlului nu apare din cauza unor restricții tehnice',
		value: 'titluincorect',
	},
	{
		label: '\{\{inițialămică\}\}: titlul corect al acestui articol este cu inițială mică dar nu apare din cauza unor restricții tehnice',
		value: 'inițialămică',
	},
	{
		label: '\{\{șterge|Motiv\}\}: această pagină a fost propusă pentru ștergere',
		value: 'șterge' },
	{
		label: '\{\{ștergere rapidă\}\}: această pagină a fost propusă pentru ștergere rapidă',
		value: 'ștergere rapidă',
	},
	{
		label: '\{\{eveniment sportiv viitor\}\}: acest articol este despre un eveniment sportiv viitor',
		value: 'eveniment sportiv viitor' },
	{
		label: '\{\{eveniment sportiv curent\}\}: acest articol este despre un eveniment sportiv curent',
		value: 'eveniment sportiv curent',
	}
];

// Tags for REDIRECTS start here

Twinkle.tag.spellingList = [
/*	{
		label: '{{R from abbreviation}}: redirect from a title with an abbreviation',
		value: 'R from abbreviation' 
	},
	{
		label: '{{R to list entry}}: redirect to a \"list of minor entities\"-type article which is a collection of brief descriptions for subjects not notable enough to have separate articles',
		value: 'R to list entry' 
	},
	{
		label: '{{R to section}}: sames as {{R to list entry}}, but when list is more sectionlike in organization, such as list of fictional characters in a fictional universe.',
		value: 'R to section' 
	},
	{
		label: '{{R from misspelling}}: redirect from a misspelling or typographical error',
		value: 'R from misspelling' 
	},
	{
		label: '{{R from alternative spelling}}: redirect from a title with a different spelling',
		value: 'R from alternative spelling' 
	},
	{
		label: '{{R from plural}}: redirect from a plural word to the singular equivalent',
		value: 'R from plural' 
	},
	{
		label: '{{R from related word}}: redirect from a related word',
		value: 'R from related word' 
	},
	{
		label: '{{R with possibilities}}: redirect from a title for a topic more detailed than what is currently provided on the target page, or section of that page, hence something which can and should be expanded',
		value: 'R with possibilities' 
	},
	{
		label: '{{R from member}}: redirect from a person who is a member of a group to more general related topics, such as the group, organization, ensemble or team that he or she belongs to',
		value: 'R from member' 
	},
	{
		label: '{{R from other capitalisation}}: redirect from a title with another method of capitalisation',
		value: 'R from other capitalisation'
	}*/
];

Twinkle.tag.alternativeList = [
/*	{
		label: '{{R from alternative name}}: redirect from a title that is another name, a pseudonym, a nickname, or a synonym',
		value: 'R from alternative name' 
	},
	{
		label: '{{R from full name}}: redirect from a title that is a complete or more complete name',
		value: 'R from full name' 
	},
	{
		label: '{{R from surname}}: redirect from a title that is a surname',
		value: 'R from surname' 
	},
	{
		label: '{{R from historic name}}: redirect from a title that is another name, a pseudonym, a nickname, or a synonym that has a significant historic past as a region, state, principate\'s holding, city, city-state or such, but which region has been subsumed into a modern era municipality, district or state, or otherwise suffered from a name change over time',
		value: 'R from historic name' 
	},
	{
		label: '{{R from scientific name}}: redirect from the scientific name to the common name',
		value: 'R from scientific name' 
	},
	{
		label: '{{R to scientific name}}: redirect from the common name to the scientific name',
		value: 'R to scientific name' 
	},
	{
		label: '{{R from name and country}}: redirect from the specific name to the briefer name',
		value: 'R from name and country' 
	},
	{
		label: '{{R from alternative language}}: redirect from an English name to a name in another language, or vice-versa',
		value: 'R from alternative language' 
	},
	{
		label: '{{R from ASCII}}: redirect from a title in basic ASCII to the formal article title, with differences that are not diacritical marks (accents, umlauts, etc.)',
		value: 'R from ASCII' 
	},
	{
		label: '{{R from title without diacritics}}: redirect to the article title with diacritical marks (accents, umlauts, etc.)',
		value: 'R from title without diacritics'
	}*/
];

Twinkle.tag.administrativeList = [
/*	{
		label: '{{R from merge}}: redirect from a merged page in order to preserve its edit history',
		value: 'R from merge' 
	},
	{
		label: '{{R to disambiguation page}}: redirect to a disambiguation page',
		value: 'R to disambiguation page' 
	},
	{
		label: '{{R from duplicated article}}: redirect to a similar article in order to preserve its edit history',
		value: 'R from duplicated article' 
	},
	{
		label: '{{R to decade}}: redirect from a year to the decade article',
		value: 'R to decade' 
	},
	{
		label: '{{R from shortcut}}: redirect from a Wikipedia shortcut',
		value: 'R from shortcut' 
	},
	{
		label: '{{R from CamelCase}}: redirect from a CamelCase title',
		value: 'R from CamelCase' 
	},
	{
		label: '{{R from EXIF}}: redirect of a wikilink created from JPEG EXIF information (i.e. the \"metadata\" section on some image description pages)',
		value: 'R from EXIF' 
	},
	{
		label: '{{R from school}}: redirect from a school article that had very little information',
		value: 'R from school'
	}*/
];

// maintenance tags for FILES start here

Twinkle.tag.file = {};

Twinkle.tag.file.licenseList = [
	{ label: '{{Non-free reduce}}: Fișier neliber la rezoluție prea mare', value: 'Non-free reduce' },
	{ label: '{{fflffs}}: Fișier fără sursă și fără licență', value: 'subst:fflffs' },
	{ label: '{{ffl}}: Fișier fără licență', value: 'subst:ffl' },
	{ label: '{{ffs}}: Fișier fără sursă', value: 'subst:ffs' },
	{ label: '{{IUCFD}}: Fișier neliber fără justificare a utilizării cinstite', value: 'subst:IUCFD' },
];

Twinkle.tag.file.cleanupList = [
];

Twinkle.tag.file.qualityList = [
];

Twinkle.tag.file.commonsList = [
	{ label: '{{Transferabil la Commons}}:fișier liber ce ar trebui copiat la Commons', value: 'Transferabil la Commons' },
	{ label: '{{Now Commons}}: fișierul a fost transferat la Commons', value: 'NowCommons' },
	{ label: '{{Shadows Commons}}: La Commons există un fisier cu același nume', value: 'Shadows Commons' },
	{ label: '{{FOP Romania}}: Fișierul nu poate fi mutat la Commons, deoarece reprezintă o operă de arhitectură recentă', value: 'FOP Romania' }
];

Twinkle.tag.file.replacementList = [
];


// Set to true if template can be grouped into {{articleissues}}
Twinkle.tag.groupHash = {
	'ajutor': true,
	'curățenie': true,
	'wikizare': true,
	'necategorizate': true,
 	'extinde': true,
	'popcat': false,
	'punct de vedere mondial': false,
	'articol neverificat': true,
	'verificare': false,
	'divide': false,
	'orfan': true,
	'fără introducere': true,
	'interlingual': true,
	'note de subsol': true,
	'acuratețe': true,
	'copyvio': false,
	'referințe': true,
	'legături externe': true,
	'original': true,
	'PDVN': true,
	'notabilitate': true,
	'neenciclopedic': true,
	'toponimie': true,
	'conținut': true,
	'dezvoltare': false,
	'modific acum': false,
	'expert': false,
	'în desfășurare': false,
	'titluincorect': false,
	'inițialămică': false,
	'șterge': false,
	'ștergere rapidă': false,
	'eveniment sportiv viitor': false,
	'eveniment sportiv curent': false,
	'ton nepotrivit': true,
	'diacritice': true,
	'ortografie': true,
	'de corectat': true,
	'ghilimele': true,
	'de tradus în alte limbi': true,
	'listă': true,
	'traducere automată': true,
};

Twinkle.tag.callbacks = {
	main: function( pageobj ) {
		var params = pageobj.getCallbackParameters();
		var tagRe, tagText = '', summaryText = 'Adăugat';
		var summaryHelperTemplateMention = '';
		var tags = [], groupableTags = [];

		var pageText = pageobj.getPageText();
		var tagTimes = {};
		var addedTags = Array();

		var formatTagBrackets = function(tagName, tagTime, extra) {
			return '{{' + tagName + (tagTime && tagTime.length > 0 ? ('|date=' + tagTime) : '') + (extra ? extra : '') + '}}';
		}
		var formatTagNoBrackets = function(tagName, tagTime) {
			return '|' + tagName + '=' + tagTime;
		}
		
		var getAddTag = function(formatterFunction) {
			return function friendlytagAddTag( tagIndex, tagName ) {
				var currentTag = "";
				if( tagName === 'necat' || tagName === 'necategorizate' || tagName === 'interlingual' || tagName === 'de tradus în alte limbi') {
					pageText += '\n\n' + formatTagBrackets(tagName, '{{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}}');
				} else {
					if( tagName === 'punct de vedere mondial' ) {
						currentTag += formatTagBrackets(params.globalizeSubcategory)
					}
	
					var thisMonth = new Date(Date.now());
					var formatMonth = thisMonth.getMonthName() + ' ' + thisMonth.getFullYear();
					// prompt for other parameters, based on the tag
					switch( tagName ) {
						case 'copyvio':
							var url = prompt('Introduceți un URL de la care s-a copiat textul.  \n' +
								"Faceti click pe OK dacă nu știți.  Pentru a renunța la eticheta {{copyvio}}, faceți click pe Cancel.", "");
							if (url === null) {
								return true;
							} else if (url !== "") {
								currentTag += formatTagBrackets(tagName, formatMonth, '|url=' + url);
							}
							break;
						case 'verificare':
							var verif_value = prompt('Specificați ce trebuie verificat.  \n' +
								"Faceți click pe OK pentru a sări peste acest pas. Pentru a anula plasarea etichetei {{verificare}}, faceți click pe Cancel.", "");
							if (verif_value === null) {
								return true;
							} else if (verif_value !== "") {
								currentTag += formatTagBrackets(tagName, formatMonth, '|1=' + verif_value);
							}
							break;
						case 'detradus':
							var langname = prompt('Introduceți limba în care e scris articolul.  \n' +
								"Faceți click pe OK dacă nu știți. Pentru a sări eticheta {{detradus}}, faceți click pe Cancel.", "");
							var section = null;
							if (langname !== null) {
								section = prompt('Introduceți partea din articol scrisă în altă limbă.  \n' +
								"Faceți click pe OK dacă e vorba de tot articolul. Pentru a sări eticheta {{detradus}}, faceți click pe Cancel.", "");
							}
							if (langname === null || section === null) {
								return true;
							} else {
								text = '';
								if (langname !== "") {
									text += '|1=' + langname;
								}
								if (section !== "") {
									text += '|ce=' + section;
								}
								currentTag += formatTagBrackets(tagName, formatMonth, text);
							}
							break;
						case 'unește':
						case 'unește cu':
						case 'unește din':
							var param = prompt('Introduceți titlul celuilalt articol implicat în unire.  \n' +
								"Pentru mai multe articole, separați-le cu simbolul pipe (|).  \n" +
								"Informația este obligatorie.  Faceți click pe OK când terminați, sau pe Cancel pentru a renunța la eticheta de unire.", "");
							if (param === null) {
								return true;
							} else if (param !== "") {
								currentTag += formatTagBrackets(tagName, '', '|' + param);
							}
							break;
						default:
							var tagTime = tagTimes[tagName];
							if (!tagTime) {
								tagTime = formatMonth;
							}
							currentTag += formatterFunction(tagName, tagTime);
							break;
					}
					
					tagText += currentTag;
				}

				
				if (!tagTimes[tagName]) {
					addedTags.push('{{[[Format:' + tagName + '|' + tagName + ']]}}');
				}
			};
		}
		var i;
		if( Twinkle.tag.mode !== 'redirect' ) {
			// Check for preexisting tags and separate tags into groupable and non-groupable arrays
			for( i = 0; i < params.tags.length; i++ ) {
				tagRegexString = params.tags[i].replace('ș', '\\u0219').replace('ț', '\\u021B').replace('ă', '\\u0103');
				//Morebits.status.info('Info', 'Searching ' + tagRegexString + ' in page');
				tagRe = new RegExp( '(\\{\\{' + tagRegexString + '(\\||\\}\\}))', 'im' );
				//Morebits.status.info('Info', 'Matching ' + tagRe + ' in page');
				if( !tagRe.exec( pageText ) ) {
					//Morebits.status.info('Info', 'Tag groupable: ' + Twinkle.tag.groupHash[ params.tags[i] ]);
					if( Twinkle.tag.groupHash[ params.tags[i] ] && 
							(params.tags[i] !== 'punct de vedere mondial' || params.globalizeSubcategory === 'globalize' ) &&
							(params.tags[i] !== 'notability' || params.notabilitySubcategory === 'none' )) {
						// don't add to multipleissues for globalize/notability subcats
						groupableTags = groupableTags.concat( params.tags[i] );
					} else {
						tags = tags.concat( params.tags[i] );
					}
				} else {
					Morebits.status.info( 'Info', 'Găsit {{' + params.tags[i] +
						'}} în articol... exclud' );
				}
				//Morebits.status.info('Info', 'Found ' + groupableTags.length + ' groupable tags: ' + groupableTags);
			}


			var miOldStyleRegex = /\{\{(probleme\s?(articol)?)\s*\|([^{]+)\}\}/im;
			var miOldStyleTest = miOldStyleRegex.exec(pageText);

			if( miOldStyleTest && groupableTags.length > 0 ) {
				Morebits.status.info( 'Info', 'Adaug etichete suportate în eticheta {{problemearticol}} existentă' );

				if( miOldStyleTest ) {
					// convert tags from old-style to new-style
					var split = miOldStyleTest[3].split("|");
					$.each(split, function(_, eachSplit){
						var splitParts = eachSplit.split("=");
						tagTimes[splitParts[0]] = splitParts[1];
						groupableTags.push(splitParts[0]);
					});
				}

				groupableTags.sort();
				tagText = "";

				totalTags = groupableTags.length;
				$.each(groupableTags, getAddTag(formatTagNoBrackets));

				pageText = pageText.replace(miOldStyleRegex, "{{$1|" + tagText + "}}\n");

				summaryHelperTemplateMention = ' (în {{[[Format:problemearticol|problemearticol]]}})';

				tagText = "";
			} else if( params.group && groupableTags.length >= 3 ) {
				Morebits.status.info( 'Info', 'Grupez etichete suportate în {{problemearticol}}' );

				groupableTags.sort();
				tagText += '{{problemearticol|\n';

				totalTags = groupableTags.length;
				$.each(groupableTags, getAddTag(formatTagNoBrackets));

				summaryHelperTemplateMention = ' (în {{[[Format:Problemearticol|problemearticol]]}})';
				tagText += '}}\n';
			} else {
				tags = tags.concat( groupableTags );
			}
		} else {
			// Check for pre-existing tags
			for( i = 0; i < params.tags.length; i++ ) {
				tagRe = new RegExp( '(\\{\\{' + params.tags[i] + '(\\||\\}\\}))', 'im' );
				if( !tagRe.exec( pageText ) ) {
					tags = tags.concat( params.tags[i] );
				} else {
					Morebits.status.info( 'Info', 'Găsit deja {{' + params.tags[i] +
						'}} pe redirecționare... exclud' );
				}
			}
		}

		tags.sort();
		$.each(tags, getAddTag(formatTagBrackets));
		$.each(addedTags, function(tagIdx, tag) {
			summaryText += ' ' + tag;
			if (tagIdx < addedTags.length - 1) {
				summaryText += tagIdx == addedTags.length - 2 ? ' și' : ',';
			}
		});
		summaryText += summaryHelperTemplateMention;

		if( Twinkle.tag.mode === 'redirect' ) {
			pageText += tagText;
		} else {
			// smartly insert the new tags after any hatnotes. Regex is a bit more
			// complicated than it'd need to be, to allow templates as parameters,
			// and to handle whitespace properly.
			pageText = pageText.replace(/^\s*(?:((?:\s*\{\{\s*(?:despre|titlu corect|pentru|deznotă|alteutilizări|see\s?(?:also|wiktionary)|selfref|the)\d*\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\})+(?:\s*\n)?)\s*)?/i,
				"$1" + tagText);
		}
		summaryText += ' ' + Twinkle.getPref('summaryAd');

		pageobj.setPageText(pageText);
		pageobj.setEditSummary(summaryText);
		pageobj.setWatchlist(Twinkle.getFriendlyPref('watchTaggedPages'));
		pageobj.setMinorEdit(Twinkle.getFriendlyPref('markTaggedPagesAsMinor'));
		pageobj.setCreateOption('nocreate');
		pageobj.save();
		
		if( Twinkle.getFriendlyPref('markTaggedPagesAsPatrolled') ) {
			pageobj.patrol();
		}
	},

	file: function friendlytagCallbacksFile(pageobj) {
		var text = pageobj.getPageText();
		var params = pageobj.getCallbackParameters();
		var summary = "Adaug ";

		// Add in maintenance tags
		if (params.tags.length) {

			var tagtext = "";
			$.each(params.tags, function(k, tag) {
				tagtext += "{{" + (tag === "Do not move to Commons_reason" ? "Do not move to Commons" : tag);

				var input;
				switch (tag) {
					case "subst:ncd":
						/* falls through */
					case "Keep local":
						input = prompt( "{{" + (tag === "subst:ncd" ? "Now Commons" : tag) +
							"}} - Enter the name of the image on Commons (if different from local name), excluding the File: prefix:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += '|1=' + input;
						}
						break;
					case "Rename media":
						input = prompt( "{{Rename media}} - Enter the new name for the image (optional):", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|1=" + input;
						}
						input = prompt( "{{Rename media}} - Enter the reason for the rename (optional):", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|2=" + input;
						}
						break;
					case "Cleanup image":
						/* falls through */
					case "Cleanup SVG":
						input = prompt( "{{" + tag + "}} - Enter the reason for cleanup (required). To skip the tag, click Cancel:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|1=" + input;
						}
						break;
					case "Image-Poor-Quality":
						input = prompt( "{{Image-Poor-Quality}} - Enter the reason why this image is so bad (required). To skip the tag, click Cancel:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|1=" + input;
						}
						break;
					case "Low quality chem":
						input = prompt( "{{Low quality chem}} - Enter the reason why the diagram is disputed (required). To skip the tag, click Cancel:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|1=" + input;
						}
						break;
					case "PNG version available":
						/* falls through */
					case "SVG version available":
						/* falls through */
					case "Obsolete":
						/* falls through */
					case "Redundant":
						input = prompt( "{{" + tag + "}} - Enter the name of the file which replaces this one (required). To skip the tag, click Cancel:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|1=" + input;
						}
						break;
					case "Do not move to Commons_reason":
						input = prompt( "{{Do not move to Commons}} - Enter the reason why this image should not be moved to Commons (required). To skip the tag, click Cancel:", "" );
						if (input === null) {
							return true;  // continue
						} else if (input !== "") {
							tagtext += "|reason=" + input;
						}
						break;
					default:
						break;  // don't care
				}

				if (tag === "Should be SVG") {
					tagtext += "|" + params.svgSubcategory;
				}

				tagtext += "}}\n";

				summary += "{{" + tag + "}}, ";

				return true;  // continue
			});

			text = tagtext + text;
		}

		pageobj.setPageText(text);
		pageobj.setEditSummary(summary.substring(0, summary.length - 2) + Twinkle.getPref('summaryAd'));
		pageobj.setWatchlist(Twinkle.getFriendlyPref('watchTaggedPages'));
		pageobj.setMinorEdit(Twinkle.getFriendlyPref('markTaggedPagesAsMinor'));
		pageobj.setCreateOption('nocreate');
		pageobj.save();

		if( Twinkle.getFriendlyPref('markTaggedPagesAsPatrolled') ) {
			pageobj.patrol();
		}
	}
};

Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
	var form = e.target;
	var params = {};

	switch (Twinkle.tag.mode) {
		case 'article':
			if( Twinkle.getFriendlyPref('customTagList').length ) {
				params.tags = form.getChecked( 'notice' ).concat( form.getChecked( 'problem' ) ).concat( form.getChecked( 'maintenance' ) ).concat( form.getChecked( 'custom' ) );
			} else {
				params.tags = form.getChecked( 'notice' ).concat( form.getChecked( 'problem' ) ).concat( form.getChecked( 'maintenance' ) );
			}
			params.group = form.group.checked;
			params.globalizeSubcategory = form.getChecked( 'problem.globalize' );
			params.globalizeSubcategory = params.globalizeSubcategory ? params.globalizeSubcategory[0] : null;
			params.notabilitySubcategory = form.getChecked( 'problem.notability' );
			params.notabilitySubcategory = params.notabilitySubcategory ? params.notabilitySubcategory[0] : null;
			break;
		case 'file':
			params.svgSubcategory = form["imageTags.svgCategory"] ? form["imageTags.svgCategory"].value : null;
			params.tags = form.getChecked( 'imageTags' );
			break;
		case 'redirect':
			params.tags = form.getChecked( 'administrative' ).concat( form.getChecked( 'alternative' ) ).concat( form.getChecked( 'spelling' ) );
			break;
		default:
			alert("Twinkle.tag: mod necunoscut: " + Twinkle.tag.mode);
			break;
	}

	if( !params.tags.length ) {
		alert( 'Selectați măcar o etichetă!' );
		return;
	}

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

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Etichetare finalizată, articolul va fi reîncărcat în câteva secunde";
	if (Twinkle.tag.mode === 'redirect') {
		Morebits.wiki.actionCompleted.followRedirect = false;
	}

	var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Etichetare " + Twinkle.tag.mode);
	wikipedia_page.setCallbackParameters(params);
	switch (Twinkle.tag.mode) {
		case 'article':
			/* falls through */
		case 'redirect':
			wikipedia_page.load(Twinkle.tag.callbacks.main);
			return;
		case 'file':
			wikipedia_page.load(Twinkle.tag.callbacks.file);
			return;
		default:
			alert("Twinkle.tag: mod necunoscut: " + Twinkle.tag.mode);
			break;
	}
};

/*
 ****************************************
 *** friendlytalkback.js: Talkback module
 ****************************************
 * Mode of invocation:     Tab ("TB")
 * Active on:              Existing user talk pages
 * Config directives in:   FriendlyConfig
 */

Twinkle.talkback = function friendlytalkback() {
	if( mw.config.get('wgNamespaceNumber') === 3 ) {
		var username = mw.config.get('wgTitle').split( '/' )[0].replace( /\"/, "\\\""); // only first part before any slashes
		twAddPortletLink(function() { Twinkle.talkback.callback(username); }, "Re", "friendly-talkback", "Răspuns rapid");
	}
};

Twinkle.talkback.callback = function friendlytalkbackCallback( uid ) {
	if( uid === mw.config.get('wgUserName') ){
		alert( 'Talkback pe propria pagină de discuții nu are sens.' );
		return;
	}

	var Window = new Morebits.simpleWindow( 600, 350 );
	Window.setTitle( "Talkback" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "About {{talkback}}", "Template:Talkback" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#talkback" );

	var form = new Morebits.quickForm( Twinkle.talkback.callback.evaluate );

	form.append( { type: 'radio', name: 'tbtarget',
				list: [ {
						label: 'Pagina mea de discuție',
						value: 'mytalk',
						checked: 'true' },
					{
						label: 'Pagina altcuiva de discuție',
						value: 'usertalk' },
					{
						label: 'Altă pagină',
						value: 'other' } ],
				event: Twinkle.talkback.callback.change_target
			} );

	form.append( {
			type: 'field',
			label: 'Work area',
			name: 'work_area'
		} );

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

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

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

Twinkle.talkback.prev_page = '';
Twinkle.talkback.prev_section = '';
Twinkle.talkback.prev_message = '';

Twinkle.talkback.callback.change_target = function friendlytagCallbackChangeTarget(e) {
	var value = e.target.values;
	var root = e.target.form;
	var old_area;

	if(root.section) {
		Twinkle.talkback.prev_section = root.section.value;
	}
	if(root.message) {
		Twinkle.talkback.prev_message = root.message.value;
	}
	if(root.page) {
		Twinkle.talkback.prev_page = root.page.value;
	}

	for( var i = 0; i < root.childNodes.length; ++i ) {
		var node = root.childNodes[i];
		if (node instanceof Element && node.getAttribute( 'name' ) === 'work_area' ) {
			old_area = node;
			break;
		}
	}
	var work_area = new Morebits.quickForm.element( { 
			type: 'field',
			label: 'Talkback information',
			name: 'work_area'
		} );

	switch( value ) {
		case 'mytalk':
			/* falls through */
		default:
			work_area.append( { 
					type:'input',
					name:'section',
					label:'Secțiunea (opțional)',
					tooltip:'Secțiunea din pagina de discuții unde ați lăsat mesajul.',
					value: Twinkle.talkback.prev_section
				} );
			break;
		case 'usertalk':
			work_area.append( { 
					type:'input',
					name:'page',
					label:'Utilizatorul',
					tooltip:'Numele utilizatorului pe pagina de discuție a căruia ați lăsat mesajul.',
					value: Twinkle.talkback.prev_page
				} );
			
			work_area.append( { 
					type:'input',
					name:'section',
					label:'Secțiunea (opțional)',
					tooltip:'Titlul secțiunii unde ați lăsat mesajul.',
					value: Twinkle.talkback.prev_section
				} );
			break;
		case 'other':
			work_area.append( { 
					type:'input',
					name:'page',
					label:'Numele paginii',
					tooltip:'Numele paginii unde ați lăsat mesajul.',
					value: Twinkle.talkback.prev_page
				} );
			
			work_area.append( { 
					type:'input',
					name:'section',
					label:'Secțiunea (opțional)',
					tooltip:'Secțiunea din pagină unde ați lăsat mesajul. Lăsați gol dacă nu vreți legătură direct spre secțiune.',
					value: Twinkle.talkback.prev_section
				} );
			break;
	}

	if (value !== "an") {
		work_area.append( { type:'textarea', label:'Mesaj suplimentar (opțional):', name:'message', tooltip:'Un mesaj pe care doriți să-l lăsați sub formatul răspuns. Semnătura va fi adăugată automat la sfârșitul mesajului.' } );
	}

	work_area = work_area.render();
	root.replaceChild( work_area, old_area );
	root.message.value = Twinkle.talkback.prev_message;
};

Twinkle.talkback.callback.evaluate = function friendlytalkbackCallbackEvaluate(e) {
	var tbtarget = e.target.getChecked( 'tbtarget' )[0];
	var page = null;
	var section = e.target.section.value;
	if( tbtarget === 'usertalk' || tbtarget === 'other' ) {
		page = e.target.page.value;
		
		if( tbtarget === 'usertalk' ) {
			if( !page ) {
				alert( 'Trebuie să specificați numele utilizatorului pe a cărui pagină ați lăsat mesajul.' );
				return;
			}
		} else {
			if( !page ) {
				alert( 'Trebuie să specificați numele complet al paginii dacă nu este pagina de discuție a cuiva.' );
				return;
			}
		}
	} else if (tbtarget === "an") {
		page = e.target.noticeboard.value;
	}

	var message = e.target.message.value;

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( e.target );

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Răspuns realizat; pagina va fi imediat reîncărcată";

	var talkpage = new Morebits.wiki.page(mw.config.get('wgPageName'), "Se adaugă răspuns");
	var tbPageName = (tbtarget === 'mytalk') ? mw.config.get('wgUserName') : page;

	var text;
	if ( tbtarget === "an" ) {
		text = "\n== " + Twinkle.getFriendlyPref('adminNoticeHeading') + " ==\n{{subst:ANI-notice|thread=";
		text += section + "|noticeboard=" + tbPageName + "}}~~~~";

		talkpage.setEditSummary("Notificare discuție AN/ANI" + Twinkle.getPref('summaryAd'));
	} else {
		//clean talkback heading: strip section header markers, were erroneously suggested in the documentation
		text = '\n==' + Twinkle.getFriendlyPref('talkbackHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, "$1") + '==\n{{mesaj|';
		text += tbPageName;

		text += (tbtarget === 'mytalk') ? '' : '|pd=1';

		if( section ) {
			text += '|' + section;
		}

		text += '|ts=~~~~~}}';

		if( message ) {
			text += '\n' + message + '  ~~~~';
		} else if( Twinkle.getFriendlyPref('insertTalkbackSignature') ) {
			text += '\n~~~~';
		}

		talkpage.setEditSummary("Răspuns ([[" + (tbtarget === 'other' ? '' : 'Discuție Utilizator:') + tbPageName +
			(section ? ('#' + section) : '') + "]])" + Twinkle.getPref('summaryAd'));
	}

	talkpage.setAppendText(text);
	talkpage.setCreateOption('recreate');
	talkpage.setMinorEdit(Twinkle.getFriendlyPref('markTalkbackAsMinor'));
	talkpage.setFollowRedirect(true);
	talkpage.append();
};

/*
 ****************************************
 *** friendlywelcome.js: Welcome module
 ****************************************
 * Mode of invocation:     Tab ("Wel"), or from links on diff pages
 * Active on:              Existing user talk pages, diff pages
 * Config directives in:   FriendlyConfig
 */

Twinkle.welcome = function friendlywelcome() {
	if( Morebits.queryString.exists( 'friendlywelcome' ) ) {
		if( Morebits.queryString.get( 'friendlywelcome' ) === 'auto' ) {
			Twinkle.welcome.auto();
		} else {
			Twinkle.welcome.semiauto();
		}
	} else {
		Twinkle.welcome.normal();
	}
};

Twinkle.welcome.auto = function() {
	if( Morebits.queryString.get( 'action' ) !== 'edit' ) {
		// userpage not empty, aborting auto-welcome
		return;
	}

	Twinkle.welcome.welcomeUser();
};

Twinkle.welcome.semiauto = function() {
	Twinkle.welcome.callback( mw.config.get( 'wgTitle' ).split( '/' )[0].replace( /\"/, "\\\"") );
};

Twinkle.welcome.normal = function() {
	if( Morebits.queryString.exists( 'diff' ) ) {
		// check whether the contributors' talk pages exist yet
		var $oList = $("div#mw-diff-otitle2 span.mw-usertoollinks a.new:contains(talk)").first();
		var $nList = $("div#mw-diff-ntitle2 span.mw-usertoollinks a.new:contains(talk)").first();

		if( $oList.length > 0 || $nList.length > 0 ) {
			var spanTag = function( color, content ) {
				var span = document.createElement( 'span' );
				span.style.color = color;
				span.appendChild( document.createTextNode( content ) );
				return span;
			};

			var welcomeNode = document.createElement('strong');
			var welcomeLink = document.createElement('a');
			welcomeLink.appendChild( spanTag( 'Black', '[' ) );
			welcomeLink.appendChild( spanTag( 'Goldenrod', 'welcome' ) );
			welcomeLink.appendChild( spanTag( 'Black', ']' ) );
			welcomeNode.appendChild(welcomeLink);

			if( $oList.length > 0 ) {
				var oHref = $oList.attr("href");

				var oWelcomeNode = welcomeNode.cloneNode( true );
				oWelcomeNode.firstChild.setAttribute( 'href', oHref + '&' + Morebits.queryString.create( { 'friendlywelcome': Twinkle.getFriendlyPref('quickWelcomeMode')==='auto'?'auto':'norm' } ) + '&' + Morebits.queryString.create( { 'vanarticle': mw.config.get( 'wgPageName' ).replace(/_/g, ' ') } ) );
				$oList[0].parentNode.parentNode.appendChild( document.createTextNode( ' ' ) );
				$oList[0].parentNode.parentNode.appendChild( oWelcomeNode );
			}

			if( $nList.length > 0 ) {
				var nHref = $nList.attr("href");

				var nWelcomeNode = welcomeNode.cloneNode( true );
				nWelcomeNode.firstChild.setAttribute( 'href', nHref + '&' + Morebits.queryString.create( { 'friendlywelcome': Twinkle.getFriendlyPref('quickWelcomeMode')==='auto'?'auto':'norm' } ) + '&' + Morebits.queryString.create( { 'vanarticle': mw.config.get( 'wgPageName' ).replace(/_/g, ' ') } ) );
				$nList[0].parentNode.parentNode.appendChild( document.createTextNode( ' ' ) );
				$nList[0].parentNode.parentNode.appendChild( nWelcomeNode );
			}
		}
	}
	if( mw.config.get( 'wgNamespaceNumber' ) === 3 ) {
		var username = mw.config.get( 'wgTitle' ).split( '/' )[0].replace( /\"/, "\\\""); // only first part before any slashes
		twAddPortletLink( function(){ Twinkle.welcome.callback(username); }, "BV", "friendly-welcome", "Bun venit");
	}
};

Twinkle.welcome.welcomeUser = function welcomeUser() {
	Morebits.status.init( document.getElementById('bodyContent') );

	var params = {
		value: Twinkle.getFriendlyPref('quickWelcomeTemplate'),
		article: Morebits.queryString.exists( 'vanarticle' ) ? Morebits.queryString.get( 'vanarticle' ) : '',
		mode: 'auto'
	};

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Bun venit realizat, pagina de discuții se reîncarcă în câteva secunde";

	var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "User talk page modification");
	wikipedia_page.setFollowRedirect(true);
	wikipedia_page.setCallbackParameters(params);
	wikipedia_page.load(Twinkle.welcome.callbacks.main);
};

Twinkle.welcome.callback = function friendlywelcomeCallback( uid ) {
	var Window = new Morebits.simpleWindow( 600, 400 );
	Window.setTitle( "Welcome user" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Welcoming Committee", "WP:WC" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#welcome" );

	var form = new Morebits.quickForm( Twinkle.welcome.callback.evaluate, 'change' );

	form.append( {
			type: 'input',
			name: 'article',
			label: 'Linked article (if supported by template)',
			value:( Morebits.queryString.exists( 'vanarticle' ) ? Morebits.queryString.get( 'vanarticle' ) : '' ),
			tooltip: 'An article might be linked to the welcome if the template supports it. Leave empty for no artice to be linked.  Templates that support a linked article are marked with an asterisk.  Ignored for templates that do not support a linked article.',
			event: function( event ) {
				event.stopPropagation();
			}
		} );

	form.append( { type:'header', label:'Simple templates' } );
	form.append( { type: 'radio', name: 'simple', list: Twinkle.welcome.standardList } );

	if( Twinkle.getFriendlyPref('customWelcomeList').length ) {
		form.append( { type:'header', label:'Custom templates' } );
		form.append( { type: 'radio', name: 'custom', list: Twinkle.getFriendlyPref('customWelcomeList') } );
	}

	form.append( { type:'header', label:'Welcoming committee templates' } );
	form.append( { type: 'radio', name: 'welcomingCommittee', list: Twinkle.welcome.welcomingCommitteeList } );

	form.append( { type:'header', label:'Potential problem user templates' } );
	form.append( { type: 'radio', name: 'problem', list: Twinkle.welcome.problemList } );

	form.append( { type:'header', label:'Anonymous user templates' } );
	form.append( { type: 'radio', name: 'anonymous', list: Twinkle.welcome.anonymousList } );

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

Twinkle.welcome.standardList = [
	{
		label: '{{bunvenit}}: Bun venit standard',
		value: 'bunvenit'
	},
	{ 
		label: '{{Invitație}}: invitație la înregistrare',
		value: 'invitație',
		tooltip: 'Pentru utilizatori anonimi.'
	}
];

Twinkle.welcome.welcomingCommitteeList = [
];

Twinkle.welcome.problemList = [
];

Twinkle.welcome.anonymousList = [
];

// Set to true if template does not already have heading
Twinkle.welcome.headingHash = {
	'Welcome': true,
	'Welcomeshort': false,
	'WelcomeSimple': false,
	'Welcom': false,
	'Welcome-personal': false,
	'WelcomeMenu': true,
	'Welcomeg': true,
	'Welcomeh': false,
	'Welcome-belated': false,
	'Wel': false,
	'W-basic': true,
	'W-shout': true,
	'W-short||': true,
	'W-link': true,
	'W-graphical': true,
	'W-screen': true,
	'Welcomelaws': true,
	'Firstarticle': true,
	'Welcomevandal': false,
	'Welcomenpov': true,
	'Welcomespam': true,
	'Welcomeunsourced': true,
	'Welcomeauto': false,
	'Welcome-COI': true,
	'Welcome-anon': true,
	'Welcomeanon2': false,
	'Welc-anon||': false,
	'Welcome-anon-vandalism-fighter': false,
	'Welcome-anon-vandal': false
};

// Set to true if template already has signature
Twinkle.welcome.signatureHash = {
	'Welcome': false,
	'Welcomeshort': false,
	'WelcomeSimple': false,
	'Welcom': true,
	'Welcome-personal': false,
	'WelcomeMenu': true,
	'Welcomeg': true,
	'Welcomeh': true,
	'Welcome-belated': true,
	'Wel': false,
	'W-basic': true,
	'W-shout': true,
	'W-short||': true,
	'W-link': true,
	'W-graphical': true,
	'W-screen': true,
	'Welcomelaws': false,
	'Firstarticle': true,
	'Welcomevandal': true,
	'Welcomenpov': false,
	'Welcomespam': false,
	'Welcomeunsourced': false,
	'Welcome-COI': false,
	'Welcome-anon': false,
	'Welcomeanon2': false,
	'Welc-anon||': false,
	'Welcome-anon-vandalism-fighter': false,
	'Welcome-anon-vandal': true
};

/* Set to true if template supports article
 * name from art template parameter 
 */
Twinkle.welcome.artHash = {
	'Welcome': true,
	'Welcomeshort': false,
	'WelcomeSimple': false,
	'Welcom': false,
	'Welcome-personal': false,
	'WelcomeMenu': false,
	'Welcomeg': false,
	'Welcomeh': false,
	'Welcome-belated': false,
	'Wel': true,
	'W-basic': false,
	'W-shout': false,
	'W-short||': false,
	'W-link': false,
	'W-graphical': false,
	'W-screen': false,
	'Welcomelaws': false,
	'Firstarticle': false,
	'Welcomevandal': false,
	'Welcomenpov': false,
	'Welcomespam': false,
	'Welcomeunsourced': false,
	'Welcomeauto': true,
	'Welcome-COI': false,
	'Welcome-anon': true,
	'Welcomeanon2': true,
	'Welc-anon||': false,
	'Welcome-anon-vandalism-fighter': true,
	'Welcome-anon-vandal': false
};

/* Set to true if template supports article
 * name from vanarticle template parameter 
 */
Twinkle.welcome.vandalHash = {
	'Welcome': false,
	'Welcomeshort': false,
	'WelcomeSimple': false,
	'Welcom': false,
	'Welcome-personal': false,
	'WelcomeMenu': false,
	'Welcomeg': false,
	'Welcomeh': false,
	'Welcome-belated': false,
	'Wel': false,
	'W-basic': false,
	'W-shout': false,
	'W-short||': false,
	'W-link': false,
	'W-graphical': false,
	'W-screen': false,
	'Welcomelaws': false,
	'Firstarticle': true,
	'Welcomevandal': true,
	'Welcomenpov': true,
	'Welcomespam': true,
	'Welcomeunsourced': true,
	'Welcomeauto': false,
	'Welcome-COI': false,
	'Welcome-anon': false,
	'Welcomeanon2': false,
	'Welc-anon||': false,
	'Welcome-anon-vandalism-fighter': false,
	'Welcome-anon-vandal': true
};

Twinkle.welcome.callbacks = {
	main: function( pageobj ) {
		var params = pageobj.getCallbackParameters();
		var oldText = pageobj.getPageText();
		
		// abort if mode is auto and form is not empty
		if( pageobj.exists() && params.mode === 'auto' ) {
			Morebits.status.info( 'Warning', 'User talk page not empty; aborting automatic welcome' );
			Morebits.wiki.actionCompleted.event();
			return;
		}
		
		var text = '';
		Morebits.status.info( 'Info', 'Will add the welcome template to the ' +
			( Twinkle.getFriendlyPref('topWelcomes') ? 'top' : 'bottom' ) +
			' of the user\'s talk page.' );
		if( !Twinkle.getFriendlyPref('topWelcomes') ) {
			text += oldText + '\n';
		}
		
		if( Twinkle.welcome.headingHash[ params.value ] && Twinkle.getFriendlyPref('insertHeadings') ) {
			Morebits.status.info( 'Info', 'Will create a new heading for the welcome' );
			// strip section header markers from pref, to preserve backwards compatibility
			text += "== " + Twinkle.getFriendlyPref('welcomeHeading').replace(/^\s*=+\s*(.*?)\s*=+$\s*/, "$1") + " ==\n";
		}
		
		Morebits.status.info( 'Info', 'Will substitute the {{' + params.value + '}} welcome template' );
		text += '{{subst:' + params.value;
		
		if( Twinkle.welcome.artHash[ params.value ] ) {
			if( Twinkle.getFriendlyPref('insertUsername') && params.value.substring(2,0) !== 'W-' ) {
				Morebits.status.info( 'Info', 'Will add your username to the template' );
				text += '|' + mw.config.get('wgUserName');
			}
			
			if( params.article ) {
				Morebits.status.info( 'Info', 'Will add article link to the template' );
				text += '|art=' + params.article;
			}
		} else if( Twinkle.welcome.vandalHash[ params.value ] ) {
			if( params.article ) {
				Morebits.status.info( 'Info', 'Will add article link to the template' );
			}
			text += '|' + params.article;
			
			if( Twinkle.getFriendlyPref('insertUsername') ) {
				Morebits.status.info( 'Info', 'Will add your username to the template' );
				text += '|' + mw.config.get('wgUserName');
			}
		} else if( Twinkle.getFriendlyPref('insertUsername') ) {
			Morebits.status.info( 'Info', 'Will add your username to the template' );
			text += '|' + mw.config.get('wgUserName');
		} 
		
		text += '}}';
		
		if( !Twinkle.welcome.signatureHash[ params.value ] && Twinkle.getFriendlyPref('insertSignature') ) {
			Morebits.status.info( 'Info', 'Will add your signature after the welcome' );
			text += ' \n~~~~';
		}
		
		if( Twinkle.getFriendlyPref('topWelcomes') ) {
			text += '\n\n' + oldText;
		}
 
		var summaryText = "Adăugat format " + ( Twinkle.getFriendlyPref('maskTemplateInSummary') ? 'bun venit' : ( '{{[[Format:' + params.value + '|' + params.value + ']]}}' ) ) +
			" la pagina utilizatorului";
		pageobj.setPageText(text);
		pageobj.setEditSummary(summaryText + Twinkle.getPref('summaryAd'));
		pageobj.setMinorEdit(Twinkle.getFriendlyPref('markWelcomesAsMinor'));
		pageobj.setWatchlist(Twinkle.getFriendlyPref('watchWelcomes'));
		pageobj.setCreateOption('recreate');
		pageobj.save();
	}
};

Twinkle.welcome.callback.evaluate = function friendlywelcomeCallbackEvaluate(e) {
	// Ignore if a change to the text field triggered this event
	if( e.target.name === 'article' ) {
		return;
	}
	
	var params = {
		value: e.target.values,
		article: e.target.form.article.value,
		mode: 'manual'
	};

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

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Bun venit transmis, pagina se reîncarcă în scurt timp";

	var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Modificarea paginii de discuție a utilizatorului");
	wikipedia_page.setFollowRedirect(true);
	wikipedia_page.setCallbackParameters(params);
	wikipedia_page.load(Twinkle.welcome.callbacks.main);
};

/*
 ****************************************
 *** twinklearv.js: ARV module
 ****************************************
 * Mode of invocation:     Tab ("ARV")
 * Active on:              Existing and non-existing user pages, user talk pages, contributions pages
 * Config directives in:   TwinkleConfig
 */

Twinkle.arv = function twinklearv() {
	if ( mw.config.get('wgNamespaceNumber') === 2 || mw.config.get('wgNamespaceNumber') === 3 || 
	    ( mw.config.get('wgNamespaceNumber') === -1 && mw.config.get('wgTitle') === "Contributions" )) {

		// If we are on the contributions page, need to parse some then
		var username;
		if( mw.config.get('wgNamespaceNumber') === -1 && mw.config.get('wgTitle') === "Contributions" ) {
			username = decodeURIComponent(/user=(.+)/.exec($('div#contentSub a[title="Special:Jurnal"]').last().attr("href").replace(/\+/g, "%20"))[1]);
		} else {
			username = mw.config.get('wgTitle').split( '/' )[0]; // only first part before any slashes
		}

		if ( !username ) {
			return;
		}

		var title = mw.util.isIPAddress( username ) ? 'Report IP to administrators' : 'Report user to administrators';
		
		if (twinkleUserAuthorized) {
			twAddPortletLink(function() { Twinkle.arv.callback(username.replace( /\"/g, "\\\"")); }, "ARV", "tw-arv", title);
		} else {
			twAddPortletLink(function() { alert("Your account is too new to use Twinkle."); } , 'ARV', 'tw-arv', title);
		}
	}
};

Twinkle.arv.callback = function ( uid ) {
	if( uid === mw.config.get('wgUserName') ){
		alert( 'You don\'t want to report yourself, do you?' );
		return;
	}

	var Window = new Morebits.simpleWindow( 600, 500 );
	Window.setTitle( "Advance Reporting and Vetting" ); //Backronym
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Guide to AIV", "WP:GAIV" );
	Window.addFooterLink( "UAA instructions", "WP:UAAI" );
	Window.addFooterLink( "About SPI", "WP:SPI" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#arv" );

	var form = new Morebits.quickForm( Twinkle.arv.callback.evaluate );
	var categories = form.append( {
			type: 'select',
			name: 'category',
			label: 'Select report type: ',
			event: Twinkle.arv.callback.changeCategory
		} );
	categories.append( {
			type: 'option',
			label: 'Vandalism (WP:AIV)',
			value: 'aiv'
		} );
	categories.append( {
			type: 'option',
			label: 'Username (WP:UAA)',
			value: 'username'
		} );
	categories.append( {
			type: 'option',
			label: 'Sockpuppeteer (WP:SPI)',
			value: 'sock'
		} );
	categories.append( {
			type: 'option',
			label: 'Sockpuppet (WP:SPI)',
			value: 'puppet'
		} );
	form.append( {
			type: 'field',
			label:'Work area',
			name: 'work_area'
		} );
	form.append( { type:'submit' } );
	form.append( {
			type: 'hidden',
			name: 'uid',
			value: uid
		} );
	
	var result = form.render();
	Window.setContent( result );
	Window.display();

	// We must init the
	var evt = document.createEvent( "Event" );
	evt.initEvent( 'change', true, true );
	result.category.dispatchEvent( evt );
};

Twinkle.arv.callback.changeCategory = function (e) {
	var value = e.target.value;
	var root = e.target.form;
	var old_area;
	for( var i = 0; i < root.childNodes.length; ++i ) {
		var node = root.childNodes[i];
		if (node instanceof Element && node.getAttribute( 'name' ) === 'work_area') {
			old_area = node;
			break;
		}
	}
	var work_area = null;

	switch( value ) {
	case 'aiv':
		/* falls through */
	default:
		work_area = new Morebits.quickForm.element( { 
				type: 'field',
				label: 'Report user for vandalism',
				name: 'work_area'
			} );
		work_area.append( {
				type: 'input',
				name: 'page',
				label: 'Primary linked page: ',
				tooltip: 'Leave blank to not link to the page in the report',
				value: Morebits.queryString.exists( 'vanarticle' ) ? Morebits.queryString.get( 'vanarticle' ) : '',
				event: function(e) {
					var value = e.target.value;
					var root = e.target.form;
					if( value === '' ) {
						root.badid.disabled = root.goodid.disabled = true;
					} else {
						root.badid.disabled = false;
						root.goodid.disabled = root.badid.value === '';
					}
				}
			} );
		work_area.append( {
				type: 'input',
				name: 'badid',
				label: 'Revision ID for target page when vandalised: ',
				tooltip: 'Leave blank for no diff link',
				value: Morebits.queryString.exists( 'vanarticlerevid' ) ? Morebits.queryString.get( 'vanarticlerevid' ) : '',
				disabled: !Morebits.queryString.exists( 'vanarticle' ),
				event: function(e) {
					var value = e.target.value;
					var root = e.target.form;
					root.goodid.disabled = value === '';
				}
			} );
		work_area.append( {
				type: 'input',
				name: 'goodid',
				label: 'Last good revision ID before vandalism of target page: ',
				tooltip: 'Leave blank for diff link to previous revision',
				value: Morebits.queryString.exists( 'vanarticlegoodrevid' ) ? Morebits.queryString.get( 'vanarticlegoodrevid' ) : '',
				disabled: !Morebits.queryString.exists( 'vanarticle' ) || Morebits.queryString.exists( 'vanarticlerevid' )
			} );
		work_area.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{ 
						label: 'Vandalism after final (level 4 or 4im) warning given',
						value: 'final'
					},
					{ 
						label: 'Vandalism after recent (within 1 day) release of block',
						value: 'postblock'
					},
					{ 
						label: 'Evidently a vandalism-only account',
						value: 'vandalonly',
						disabled: mw.util.isIPAddress( root.uid.value )
					},
					{ 
						label: 'Account is evidently a spambot or a compromised account',
						value: 'spambot'
					},
					{ 
						label: 'Account is a promotion-only account',
						value: 'promoonly'
					}
				]
			} );
		work_area.append( {
				type: 'textarea',
				name: 'reason',
				label: 'Comment: '
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'username':
		work_area = new Morebits.quickForm.element( { 
				type: 'field',
				label: 'Report username violation',
				name: 'work_area'
			} );
		work_area.append ( { 
				type:'header', 
				label:'Type(s) of inappropriate username',
				tooltip: 'Wikipedia does not allow usernames that are misleading, promotional, offensive or disruptive. Domain names and e-mail addresses are likewise prohibited. These criteria apply to both usernames and signatures. Usernames that are inappropriate in another language, or that represent an inappropriate name with misspellings and substitutions, or do so indirectly or by implication, are still considered inappropriate.'
			} );
		work_area.append( {
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'Misleading username',
						value: 'misleading',
						tooltip: 'Misleading usernames imply relevant, misleading things about the contributor. For example, misleading points of fact, an impression of undue authority, or the suggestion that the account is operated by a group, project or collective rather than one individual.'
					},
					{ 
						label: 'Promotional username',
						value: 'promotional',
						tooltip: 'Promotional usernames are advertisements for a company or group.'
					},
					{ 
						label: 'Offensive username',
						value: 'offensive',
						tooltip: 'Offensive usernames make harmonious editing difficult or impossible.'
					},
					{ 
						label: 'Disruptive username',
						value: 'disruptive',
						tooltip: 'Disruptive usernames include outright trolling or personal attacks, or otherwise show a clear intent to disrupt Wikipedia.'
					}
				]
			} );
		work_area.append( {
				type: 'textarea',
				name: 'reason',
				label: 'Comment:'
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;

	case 'puppet':
		work_area = new Morebits.quickForm.element( { 
				type: 'field',
				label: 'Report suspected sockpuppet',
				name: 'work_area'
			} );
		work_area.append(
			{
				type: 'input',
				name: 'sockmaster',
				label: 'Sockpuppeteer',
				tooltip: 'The username of the sockpuppeteer (sockmaster) without the User:-prefix'
			}
		);
		work_area.append( {
				type: 'textarea',
				label: 'Evidence:',
				name: 'evidence',
				tooltip: 'Enter your evidence. It should make clear that each of these users is likely to be abusing multiple accounts. Usually this means diffs, page histories or other information that justifies why the users are a) the same and b) disruptive. This should purely be evidence and information needed to judge the matter. Avoid all other discussion that is not evidence of sockpuppetry or other multiple account abuse.'
			} );
		work_area.append( {
				type: 'checkbox',
				list: [
					{
						label: 'Request CheckUser evidence',
						name: 'checkuser',
						tooltip: 'CheckUser is a tool used to obtain technical evidence related to a sock-puppetry allegation. It will not be used without good cause, which you must clearly demonstrate. Make sure your evidence explains why CheckUser is appropriate.'
					},
					{
						label: 'Notify reported users',
						name: 'notify',
						tooltip: 'Notification is not mandatory. In many cases, especially of chronic sockpuppeteers, notification may be counterproductive. However, especially in less egregious cases involving users who has not been reported before, notification may make the cases fairer and also appear to be fairer in the eyes of the accused. Use your judgment.'
					}
				]
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'sock':
		work_area = new Morebits.quickForm.element( { 
				type: 'field',
				label: 'Report suspected sockpuppeteer',
				name: 'work_area'
			} );
		work_area.append(
			{
				type: 'dyninput',
				name: 'sockpuppet',
				label: 'Sockpuppets',
				sublabel: 'Sock: ',
				tooltip: 'The username of the sockpuppet without the User:-prefix',
				min: 2
			}
		);
		work_area.append( {
				type: 'textarea',
				label: 'Evidence:',
				name: 'evidence',
				tooltip: 'Enter your evidence. It should make clear that each of these users is likely to be abusing multiple accounts. Usually this means diffs, page histories or other information that justifies why the users are a) the same and b) disruptive. This should purely be evidence and information needed to judge the matter. Avoid all other discussion that is not evidence of sockpuppetry or other multiple account abuse.'
			} );
		work_area.append( {
				type: 'checkbox',
				list: [ {
					label: 'Request CheckUser evidence',
					name: 'checkuser',
					tooltip: 'CheckUser is a tool used to obtain technical evidence related to a sock-puppetry allegation. It will not be used without good cause, which you must clearly demonstrate. Make sure your evidence explains why CheckUser is appropriate.'
				}, {
					label: 'Notify reported users',
					name: 'notify',
					tooltip: 'Notification is not mandatory. In many cases, especially of chronic sockpuppeteers, notification may be counterproductive. However, especially in less egregious cases involving users who has not been reported before, notification may make the cases fairer and also appear to be fairer in the eyes of the accused. Use your judgment.'
				} ]
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	}
};

Twinkle.arv.callback.evaluate = function(e) {

	var form = e.target;
	var reason = "";
	var comment = "";
	if ( form.reason ) {
		comment = form.reason.value;
	}
	var uid = form.uid.value;

	var types;
	switch( form.category.value ) {

		// Report user for vandalism
		case 'aiv':
			/* falls through */
		default:
			types = form.getChecked( 'arvtype' );
			if( !types.length && comment === '' ) {
				alert( 'You must specify some reason' );
				return;
			}

			types = types.map( function(v) {
					switch(v) {
						case 'final':
							return 'vandalism after final warning';
						case 'postblock':
							return 'vandalism after recent release of block';
						case 'spambot':
							return 'account is evidently a spambot or a compromised account';
						case 'vandalonly':
							return 'actions evidently indicate a vandalism-only account';
						case 'promoonly':
							return 'account is being used only for promotional purposes';
						default:
							return 'unknown reason';
					}
				} ).join( ', ' );


			if ( form.page.value !== '' ) {
			
				// add a leading : on linked page namespace to prevent transclusion
				reason = 'On [[' + form.page.value.replace( /^(Image|Category|File):/i, ':$1:' ) + ']]';

				if ( form.badid.value !== '' ) {
					var query = {
						'title': form.page.value,
						'diff': form.badid.value,
						'oldid': form.goodid.value
					};
					reason += ' ({{diff|' + form.page.value + '|' + form.badid.value + '|' + form.goodid.value + '|diff}})';
				}
				reason += ';';
			}

			if ( types ) {
				reason += " " + types;
			}
			if (comment !== "" ) {
				reason += (reason === "" ? "" : ". ") + comment + ".";
			}
			reason += "~~~~";
			reason = reason.replace(/\r?\n/g, "\n*:");  // indent newlines

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

			Morebits.wiki.actionCompleted.redirect = "Wikipedia:Administrator intervention against vandalism";
			Morebits.wiki.actionCompleted.notice = "Reporting complete";

			var aivPage = new Morebits.wiki.page( 'Wikipedia:Administrator intervention against vandalism', 'Processing AIV request' );
			aivPage.setPageSection( 1 );
			aivPage.setFollowRedirect( true );
			
			aivPage.load( function() {
				var text = aivPage.getPageText();

				// check if user has already been reported
				if (new RegExp( "\\{\\{\\s*(?:(?:[Ii][Pp])?[Vv]andal|[Uu]serlinks)\\s*\\|\\s*(?:1=)?\\s*" + RegExp.escape( uid, true ) + "\\s*\\}\\}" ).test(text)) {
					aivPage.getStatusElement().info( 'Report already present, will not add a new one' );
					return;
				}
				aivPage.getStatusElement().status( 'Adding new report...' );
				aivPage.setEditSummary( 'Reporting [[Special:Contributions/' + uid + '|' + uid + ']].' + Twinkle.getPref('summaryAd') );
				aivPage.setAppendText( '\n*{{' + ( mw.util.isIPAddress( uid ) ? 'IPvandal' : 'vandal' ) + '|' + (/\=/.test( uid ) ? '1=' : '' ) + uid + '}} - ' + reason );
				aivPage.append();
			} );
			break;
			
		// Report inappropriate username
		case 'username':
			types = form.getChecked( 'arvtype' );
			if( !types.length ) {
				alert( 'You must specify at least one breached violation' );
				return;
			}
			types = types.map( function( v ) { return Morebits.string.toLowerCaseFirstChar(v); } );

			if ( types.length <= 2 ) {
				types = types.join( ' and ' );
			} else {
				types = [ types.slice( 0, -1 ).join( ', ' ), types.slice( -1 ) ].join( ' and ' );
			}
			var article = 'a';
			if ( /[aeiouwyh]/.test( types[0] ) ) { // non 100% correct, but whatever, inlcuding 'h' for Cockney
				article = 'an';
			}
			reason = "*{{user-uaa|1=" + uid + "}} &mdash; Violation of username policy as " + article + " " + types + " username. ";
			if (comment !== '' ) {
				reason += Morebits.string.toUpperCaseFirstChar(comment) + ". ";
			}
			reason += "~~~~";
			reason = reason.replace(/\r?\n/g, "\n*:");  // indent newlines

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

			Morebits.wiki.actionCompleted.redirect = "Wikipedia:Usernames for administrator attention";
			Morebits.wiki.actionCompleted.notice = "Reporting complete";

			var uaaPage = new Morebits.wiki.page( 'Wikipedia:Usernames for administrator attention', 'Processing UAA request' );
			uaaPage.setFollowRedirect( true );

			uaaPage.load( function() {
				var text = uaaPage.getPageText();
				
				// check if user has already been reported
				if (new RegExp( "\\{\\{\\s*user-uaa\\s*\\|\\s*(1\\s*=\\s*)?" + RegExp.escape(uid, true) + "\\s*(\\||\\})" ).test(text)) {
					uaaPage.getStatusElement().error( 'User is already listed.' );
					return;
				}
				uaaPage.getStatusElement().status( 'Adding new report...' );
				uaaPage.setEditSummary( 'Reporting [[Special:Contributions/' + uid + '|' + uid + ']].'+ Twinkle.getPref('summaryAd') );
				uaaPage.setPageText( text.replace( /List begins below this line.\s*-->/, "List begins below this line.\n-->\n" + reason ) );  // add at top
				uaaPage.save();
			} );
			break;
			
		// WP:SPI
		case "sock":
			/* falls through */
		case "puppet":
			var sockParameters = {
				evidence: form.evidence.value.rtrim(), 
				checkuser: form.checkuser.checked, 
				notify: form.notify.checked
			};

			var puppetReport = form.category.value === "puppet";
			if (puppetReport && !(form.sockmaster.value.trim())) {
				if (!confirm("You have not entered a sockmaster account for this puppet. Do you want to report this account as a sockpuppeteer instead?")) {
					return;
				}
				puppetReport = false;
			}

			sockParameters.uid = puppetReport ? form.sockmaster.value.rtrim() : uid;
			sockParameters.sockpuppets = puppetReport ? [uid] : $.map( $('input:text[@name=sockpuppet]',form), function(o){ return $(o).val(); });

			Morebits.simpleWindow.setButtonsEnabled( false );
			Morebits.status.init( form );
			Twinkle.arv.processSock( sockParameters );
			break;

	}
};

Twinkle.arv.processSock = function( params ) {
	Morebits.wiki.addCheckpoint(); // prevent notification events from causing an erronous "action completed"
	
	// notify all user accounts if requested
	if (params.notify && params.sockpuppets.length>0) {
	
		var notifyEditSummary = "Notifying about suspicion of sockpuppeteering." + Twinkle.getPref('summaryAd');
		var notifyText = "\n\n{{subst:socksuspectnotice|1=" + params.uid + "}} ~~~~";
		
		// notify user's master account
		var masterTalkPage = new Morebits.wiki.page( 'User talk:' + params.uid, 'Notifying suspected sockpuppeteer' );
		masterTalkPage.setFollowRedirect( true );
		masterTalkPage.setEditSummary( notifyEditSummary );
		masterTalkPage.setAppendText( notifyText );
		masterTalkPage.append();

		var statusIndicator = new Morebits.status( 'Notifying suspected sockpuppets', '0%' );
		var total = params.sockpuppets.length;
		var current =   0;
		
		// display status of notifications as they progress
		var onSuccess = function( sockTalkPage ) {
			var now = parseInt( 100 * ++(current)/total, 10 ) + '%';
			statusIndicator.update( now );
			sockTalkPage.getStatusElement().unlink();
			if ( current >= total ) {
				statusIndicator.info( now + ' (completed)' );
			}
		};
		
		var socks = params.sockpuppets;

		// notify each puppet account
		for( var i = 0; i < socks.length; ++i ) {
			var sockTalkPage = new Morebits.wiki.page( 'User talk:' + socks[i], "Notification for " +  socks[i] );
			sockTalkPage.setFollowRedirect( true );
			sockTalkPage.setEditSummary( notifyEditSummary );
			sockTalkPage.setAppendText( notifyText );
			sockTalkPage.append( onSuccess );
		}
	}

	// prepare the SPI report
	var text = "\n\n{{subst:SPI report|socksraw=" +
		params.sockpuppets.map( function(v) { 
				return "* {{" + ( mw.util.isIPAddress( v ) ? "checkip" : "checkuser" ) + "|1=" + v + "}}";
			} ).join( "\n" ) + "\n|evidence=" + params.evidence + " \n";
		
	if ( params.checkuser ) {
		text += "|checkuser=yes";
	}
	text += "}}";

	var reportpage = 'Wikipedia:Sockpuppet investigations/' + params.uid;

	Morebits.wiki.actionCompleted.redirect = reportpage;
	Morebits.wiki.actionCompleted.notice = "Reporting complete";

	var spiPage = new Morebits.wiki.page( reportpage, 'Retrieving discussion page' );
	spiPage.setFollowRedirect( true );
	spiPage.setEditSummary( 'Adding new report for [[Special:Contributions/' + params.uid + '|' + params.uid + ']].'+ Twinkle.getPref('summaryAd') );
	spiPage.setAppendText( text );
	spiPage.append();
	
	Morebits.wiki.removeCheckpoint();  // all page updates have been started
};

/*
 ****************************************
 *** twinklebatchdelete.js: Batch delete module (sysops only)
 ****************************************
 * Mode of invocation:     Tab ("D-batch")
 * Active on:              Existing and non-existing non-articles, and Special:PrefixIndex
 * Config directives in:   TwinkleConfig
 */


Twinkle.batchdelete = function twinklebatchdelete() {
	if( Morebits.userIsInGroup( 'sysop' ) && (mw.config.get( 'wgNamespaceNumber' ) > 0 || mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Prefixindex') ) {
		twAddPortletLink(Twinkle.batchdelete.callback, "D-batch", "tw-batch", "șterge pagini de pe această pagină sau din această categorie");
	}
};

Twinkle.batchdelete.unlinkCache = {};
Twinkle.batchdelete.callback = function twinklebatchdeleteCallback() {
	var Window = new Morebits.simpleWindow( 800, 400 );
	Window.setTitle( "Batch deletion" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#batchdelete" );

	var form = new Morebits.quickForm( Twinkle.batchdelete.callback.evaluate );
	form.append( {
			type: 'checkbox',
			list: [
				{ 
					label: 'Delete pages',
					name: 'delete_page',
					value: 'delete',
					checked: true
				},
				{
					label: 'Remove backlinks to the page',
					name: 'unlink_page',
					value: 'unlink',
					checked: true
				},
				{
					label: 'Delete redirects to deleted pages',
					name: 'delete_redirects',
					value: 'delete_redirects',
					checked: true
				}
			]
		} );
	form.append( {
			type: 'textarea',
			name: 'reason',
			label: 'Reason: '
		} );

	var query;
	if( mw.config.get( 'wgNamespaceNumber' ) === 14 ) {

		query = {
			'action': 'query',
			'generator': 'categorymembers',
			'gcmtitle': mw.config.get( 'wgPageName' ),
			'gcmlimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'prop': [ 'categories', 'revisions' ],
			'rvprop': [ 'size' ]
		};
	} else if( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Prefixindex' ) {

		var gapnamespace, gapprefix;
		if(Morebits.queryString.exists( 'from' ) )
		{
			gapnamespace = Morebits.queryString.get( 'namespace' );
			gapprefix = Morebits.string.toUpperCaseFirstChar(Morebits.queryString.get( 'from' ));
		}
		else
		{
			var pathSplit = location.pathname.split('/');
			if (pathSplit.length < 3 || pathSplit[2] !== "Special:PrefixIndex") {
				return;
			}
			var titleSplit = pathSplit[3].split(':');
			gapnamespace = mw.config.get("wgNamespaceIds")[titleSplit[0].toLowerCase()];
			if ( titleSplit.length < 2 || typeof(gapnamespace) === 'undefined' )
			{
				gapnamespace = mw.config.get("wgNamespaceIds").MAIN;
				gapprefix = pathSplit.splice(3).join('/');
			}
			else
			{
				pathSplit = pathSplit.splice(4);
				pathSplit.splice(0,0,titleSplit.splice(1).join(':'));
				gapprefix = pathSplit.join('/');
			}
		}

		query = {
			'action': 'query',
			'generator': 'allpages',
			'gapnamespace': gapnamespace ,
			'gapprefix': gapprefix,
			'gaplimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'prop' : ['categories', 'revisions' ],
			'rvprop': [ 'size' ]
		};
	} else {
		query = {
			'action': 'query',
			'generator': 'links',
			'titles': mw.config.get( 'wgPageName' ),
			'gpllimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'prop': [ 'categories', 'revisions' ],
			'rvprop': [ 'size' ]
		};
	}

	var wikipedia_api = new Morebits.wiki.api( 'Grabbing pages', query, function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//page[@ns != "' + mw.config.get("wgNamespaceIds").IMAGE + '" and not(@missing)]', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
			var list = [];
			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var object = snapshot.snapshotItem(i);
				var page = xmlDoc.evaluate( '@title', object, null, XPathResult.STRING_TYPE, null ).stringValue;
				var size = xmlDoc.evaluate( 'revisions/rev/@size', object, null, XPathResult.NUMBER_TYPE, null ).numberValue;

				var disputed = xmlDoc.evaluate( 'boolean(categories/cl[@title="Category:Contested candidates for speedy deletion"])', object, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue;
				list.push( {label:page + ' (' + size + ' bytes)' + ( disputed ? ' (DISPUTED CSD)' : '' ), value:page, checked:!disputed });
			}
			self.params.form.append( {
					type: 'checkbox',
					name: 'pages',
					list: list
				} );
			self.params.form.append( { type:'submit' } );

			var result = self.params.form.render();
			self.params.Window.setContent( result );
		} );

	wikipedia_api.params = { form:form, Window:Window };
	wikipedia_api.post();
	var root = document.createElement( 'div' );
	Morebits.status.init( root );
	Window.setContent( root );
	Window.display();
};

Twinkle.batchdelete.currentDeleteCounter = 0;
Twinkle.batchdelete.currentUnlinkCounter = 0;
Twinkle.batchdelete.currentdeletor = 0;
Twinkle.batchdelete.callback.evaluate = function twinklebatchdeleteCallbackEvaluate(event) {
	Morebits.wiki.actionCompleted.notice = 'Status';
	Morebits.wiki.actionCompleted.postfix = 'batch deletion is now complete';
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!
	var pages = event.target.getChecked( 'pages' );
	var reason = event.target.reason.value;
	var delete_page = event.target.delete_page.checked;
	var unlink_page = event.target.unlink_page.checked;
	var delete_redirects = event.target.delete_redirects.checked;
	if( ! reason ) {
		return;
	}
	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( event.target );
	if( !pages ) {
		Morebits.status.error( 'Error', 'nothing to delete, aborting' );
		return;
	}

	function toCall( work ) {
		if( work.length === 0 &&  Twinkle.batchdelete.currentDeleteCounter <= 0 && Twinkle.batchdelete.currentUnlinkCounter <= 0 ) {
			window.clearInterval( Twinkle.batchdelete.currentdeletor );
			Morebits.wiki.removeCheckpoint();
			return;
		} else if( work.length !== 0 && ( Twinkle.batchdelete.currentDeleteCounter <= Twinkle.getPref('batchDeleteMinCutOff') || Twinkle.batchdelete.currentUnlinkCounter <= Twinkle.getPref('batchDeleteMinCutOff')  ) ) {
			Twinkle.batchdelete.unlinkCache = []; // Clear the cache
			var pages = work.shift();
			Twinkle.batchdelete.currentDeleteCounter += pages.length;
			Twinkle.batchdelete.currentUnlinkCounter += pages.length;
			for( var i = 0; i < pages.length; ++i ) {
				var page = pages[i];
				var query = {
					'action': 'query',
					'titles': page
				};
				var wikipedia_api = new Morebits.wiki.api( 'Verific dacă pagina ' + page + ' există', query, Twinkle.batchdelete.callbacks.main );
				wikipedia_api.params = { page:page, reason:reason, unlink_page:unlink_page, delete_page:delete_page, delete_redirects:delete_redirects };
				wikipedia_api.post();
			}
		}
	}
	var work = pages.chunk( Twinkle.getPref('batchdeleteChunks') );
	Morebits.wiki.addCheckpoint();
	Twinkle.batchdelete.currentdeletor = window.setInterval( toCall, 1000, work );
};

Twinkle.batchdelete.callbacks = {
	main: function( self ) {
		var xmlDoc = self.responseXML;
		var normal = xmlDoc.evaluate( '//normalized/n/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
		if( normal ) {
			self.params.page = normal;
		}
		var exists = xmlDoc.evaluate( 'boolean(//pages/page[not(@missing)])', xmlDoc, null, XPathResult.BOOLEAN_TYPE, null ).booleanValue;

		if( ! exists ) {
			self.statelem.error( "Se pare că pagina nu există, poate a fost deja ștearsă." );
			return;
		}

		var query, wikipedia_api;
		if( self.params.unlink_page ) {
			query = {
				'action': 'query',
				'list': 'backlinks',
				'blfilterredir': 'nonredirects',
				'blnamespace': [0, 100], // main space and portal space only
				'bltitle': self.params.page,
				'bllimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
			};
			wikipedia_api = new Morebits.wiki.api( 'Aduc legături', query, Twinkle.batchdelete.callbacks.unlinkBacklinksMain );
			wikipedia_api.params = self.params;
			wikipedia_api.post();
		} else {
			--Twinkle.batchdelete.currentUnlinkCounter;
		}
		if( self.params.delete_page ) {
			if (self.params.delete_redirects)
			{
				query = {
					'action': 'query',
					'list': 'backlinks',
					'blfilterredir': 'redirects',
					'bltitle': self.params.page,
					'bllimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
				};
				wikipedia_api = new Morebits.wiki.api( 'Aduc redirecționări', query, Twinkle.batchdelete.callbacks.deleteRedirectsMain );
				wikipedia_api.params = self.params;
				wikipedia_api.post();
			}

			var wikipedia_page = new Morebits.wiki.page( self.params.page, 'șterg pagina ' + self.params.page );
			wikipedia_page.setEditSummary(self.params.reason + Twinkle.getPref('deletionSummaryAd'));
			wikipedia_page.deletePage(function( apiobj ) { 
					--Twinkle.batchdelete.currentDeleteCounter;
					var link = document.createElement( 'a' );
					link.setAttribute( 'href', mw.util.getUrl(self.params.page) );
					link.setAttribute( 'title', self.params.page );
					link.appendChild( document.createTextNode( self.params.page ) );
					apiobj.statelem.info( [ 'termonat (' , link , ')' ] );
				} );	
		} else {
			--Twinkle.batchdelete.currentDeleteCounter;
		}
	},
	deleteRedirectsMain: function( self ) {
		var xmlDoc = self.responseXML;
		var snapshot = xmlDoc.evaluate('//backlinks/bl/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

		var total = snapshot.snapshotLength;

		if( snapshot.snapshotLength === 0 ) {
			return;
		}

		var statusIndicator = new Morebits.status('Șterg redirecționări pentru ' + self.params.page, '0%');

		var onsuccess = function( self ) {
			var obj = self.params.obj;
			var total = self.params.total;
			var now = parseInt( 100 * ++(self.params.current)/total, 10 ) + '%';
			obj.update( now );
			self.statelem.unlink();
			if( self.params.current >= total ) {
				obj.info( now + ' (terminat)' );
				Morebits.wiki.removeCheckpoint();
			}
		};


		Morebits.wiki.addCheckpoint();
		if( snapshot.snapshotLength === 0 ) {
			statusIndicator.info( '100% (terminat)' );
			Morebits.wiki.removeCheckpoint();
			return;
		}

		var params = clone( self.params );
		params.current = 0;
		params.total = total;
		params.obj = statusIndicator;


		for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
			var title = snapshot.snapshotItem(i).value;
			var wikipedia_page = new Morebits.wiki.page( title, "șterg " + title );
			wikipedia_page.setEditSummary('[[WP:CSD#G8|G8]]: Redirect spre pagină ștearsă "' + self.params.page + '"' + Twinkle.getPref('deletionSummaryAd'));
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.deletePage(onsuccess);
		}
	},
	unlinkBacklinksMain: function( self ) {
		var xmlDoc = self.responseXML;
		var snapshot = xmlDoc.evaluate('//backlinks/bl/@title', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

		if( snapshot.snapshotLength === 0 ) {
			--Twinkle.batchdelete.currentUnlinkCounter;
			return;
		}

		var statusIndicator = new Morebits.status('Elimin legături spre ' + self.params.page, '0%');

		var total = snapshot.snapshotLength * 2;

		var onsuccess = function( self ) {
			var obj = self.params.obj;
			var total = self.params.total;
			var now = parseInt( 100 * ++(self.params.current)/total, 10 ) + '%';
			obj.update( now );
			self.statelem.unlink();
			if( self.params.current >= total ) {
				obj.info( now + ' (terminat)' );
				--Twinkle.batchdelete.currentUnlinkCounter;
				Morebits.wiki.removeCheckpoint();
			}
		};

		Morebits.wiki.addCheckpoint();
		if( snapshot.snapshotLength === 0 ) {
			statusIndicator.info( '100% (terminat)' );
			--Twinkle.batchdelete.currentUnlinkCounter;
			Morebits.wiki.removeCheckpoint();
			return;
		}
		self.params.total = total;
		self.params.obj = statusIndicator;
		self.params.current =   0;

		for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
			var title = snapshot.snapshotItem(i).value;
			var wikipedia_page = new Morebits.wiki.page( title, "Dezlegare la " + title );
			var params = clone( self.params );
			params.title = title;
			params.onsuccess = onsuccess;
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.batchdelete.callbacks.unlinkBacklinks);
		}
	},
	unlinkBacklinks: function( pageobj ) {
		var params = pageobj.getCallbackParameters();
		if( ! pageobj.exists() ) {
			// we probably just deleted it, as a recursive backlink
			params.onsuccess( { params: params, statelem: pageobj.getStatusElement() } );
			Morebits.wiki.actionCompleted();
			return;
		}
		var text;

		if( params.title in Twinkle.batchdelete.unlinkCache ) {
			text = Twinkle.batchdelete.unlinkCache[ params.title ];
		} else {
			text = pageobj.getPageText();
		}
		var old_text = text;
		var wikiPage = new Mediawiki.Page( text );
		wikiPage.removeLink( params.page );

		text = wikiPage.getText();
		Twinkle.batchdelete.unlinkCache[ params.title ] = text;
		if( text === old_text ) {
			// Nothing to do, return
			params.onsuccess( { params: params, statelem: pageobj.getStatusElement() } );
			Morebits.wiki.actionCompleted();
			return;
		}
		pageobj.setEditSummary('Elimin legături către pagina ștearsă ' + self.params.page + Twinkle.getPref('deletionSummaryAd'));
		pageobj.setPageText(text);
		pageobj.setCreateOption('nocreate');
		pageobj.save(params.onsuccess);
	}
};

/*
 ****************************************
 *** twinklebatchprotect.js: Batch protect module (sysops only)
 ****************************************
 * Mode of invocation:     Tab ("P-batch")
 * Active on:              Existing and non-existing non-articles, and Special:PrefixIndex
 * Config directives in:   TwinkleConfig
 */


Twinkle.batchprotect = function twinklebatchprotect() {
	if( Morebits.userIsInGroup( 'sysop' ) && (mw.config.get('wgNamespaceNumber') > 0 || mw.config.get('wgCanonicalSpecialPageName') == 'Prefixindex') ) {
		twAddPortletLink(Twinkle.batchprotect.callback, "P-batch", "tw-pbatch", "Protejează paginile găsite aici");
	}
};

Twinkle.batchprotect.unlinkCache = {};
Twinkle.batchprotect.callback = function twinklebatchprotectCallback() {
	var Window = new Morebits.simpleWindow( 800, 400 );
	Window.setTitle( "Batch protection" );

	var form = new Morebits.quickForm( Twinkle.batchprotect.callback.evaluate );
	form.append( {
			type: 'select',
			name: 'move',
			label: 'Move protection',
			list: [
				{ 
					label: 'Allow all users (still autoconfirmed)',
					value: '',
					selected: true
				},
				{ 
					label: 'Block new and unregistered users',
					value: 'autoconfirmed'
				},
				{
					label: 'Block all non-admin users',
					value: 'sysop'
				}
			]
		} );
	form.append( {
			type: 'select',
			name: 'edit',
			label: 'Edit protection',
			list: [
				{ 
					label: 'Allow all users',
					value: '',
					selected: true
				},
				{ 
					label: 'Block new and unregistered users',
					value: 'autoconfirmed'
				},
				{
					label: 'Block all non-admin users',
					value: 'sysop'
				}
			]
		} );
	form.append( {
			type: 'select',
			name: 'create',
			label: 'Create protection',
			list: [
				{ 
					label: 'Allow all users (still autoconfirmed)',
					value: '',
					selected: true
				},
				{ 
					label: 'Block new and unregistered users',
					value: 'autoconfirmed'
				},
				{
					label: 'Block all non-admin users',
					value: 'sysop'
				}
			]
		} );
	form.append( {
			type: 'checkbox',
			list: [
				{
					name: 'cascade',
					label: 'Cascade protection'
				}
			]
		} );
	form.append( {
			type: 'select',
			name: 'expiry',
			label: 'Expiration: ',
			list: [
				{ label: '15 minutes', value: '15 minutes' },
				{ label: '30 minutes', value: '30 minutes' },
				{ label: '45 minutes', value: '45 minutes' },
				{ label: '1 hour', value: '1 hour' },
				{ label: '2 hours', value: '2 hours' },
				{ label: '3 hours', value: '3 hours' },
				{ label: '6 hours', value: '6 hours' },
				{ label: '12 hours', value: '12 hours' },
				{ label: '1 day', value: '1 day' },
				{ label: '2 days', value: '2 days' },
				{ label: '3 days', value: '3 days' },
				{ label: '4 days', value: '4 days' },
				{ label: '5 days', value: '5 days' },
				{ label: '6 days', value: '6 days' },
				{ label: '1 week', value: '1 week' },
				{ label: '2 weeks', value: '2 weeks' },
				{ label: '1 month', value: '1 month' },
				{ label: '2 months', value: '2 months' },
				{ label: '3 months', value: '3 months' },
				{ label: '6 months', value: '6 months' },
				{ label: '1 year', value: '1 year' },
				{ label: '2 years', value: '2 years' },
				{ label: '3 years', value: '3 years' },
				{ label: '6 years', value: '6 years' },
				{ label: 'indefinite', selected: true, value:'indefinite' }
			]
		} );
	
	form.append( {
			type: 'textarea',
			name: 'reason',
			label: 'Reason: '
		} );

	var query;

	if( mw.config.get('wgNamespaceNumber') == mw.config.get("wgNamespaceIds").CATEGORY ) {

		query = {
			'action': 'query',
			'generator': 'categorymembers',
			'gcmtitle': mw.config.get('wgPageName'),
			'gcmlimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'prop': [ 'revisions' ],
			'rvprop': [ 'size' ]
		};
	} else if( mw.config.get('wgCanonicalSpecialPageName') == 'Prefixindex' ) {
		query = {
			'action': 'query',
			'generator': 'allpages',
			'gapnamespace': Morebits.queryString.exists('namespace') ? Morebits.queryString.get( 'namespace' ): document.getElementById('namespace').value,
			'gapprefix': Morebits.queryString.exists('from') ? Morebits.string.toUpperCaseFirstChar(Morebits.queryString.get( 'from' ).replace('+', ' ')) : Morebits.string.toUpperCaseFirstChar(document.getElementById('nsfrom').value),
			'gaplimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'prop' : [ 'revisions' ],
			'rvprop': [ 'size' ]
		};
	} else {
		query = {
			'action': 'query',
			'gpllimit' : Twinkle.getPref('batchMax'), // the max for sysops
			'generator': 'links',
			'titles': mw.config.get('wgPageName'),
			'prop': [ 'revisions' ],
			'rvprop': [ 'size' ]
		};

	}
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing pages', query, function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//page', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
			var list = [];
			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var object = snapshot.snapshotItem(i);
				var page = xmlDoc.evaluate( '@title', object, null, XPathResult.STRING_TYPE, null ).stringValue;
				var size = xmlDoc.evaluate( 'revisions/rev/@size', object, null, XPathResult.NUMBER_TYPE, null ).numberValue;

				list.push( {label:page + (size ? ' (' + size + ')' : '' ), value:page, checked: true });
			}
			self.params.form.append( {
					type: 'checkbox',
					name: 'pages',
					list: list
				}
			);
			self.params.form.append( { type:'submit' } );

			var result = self.params.form.render();
			self.params.Window.setContent( result );


		}  );

	wikipedia_api.params = { form:form, Window:Window };
	wikipedia_api.post();
	var root = document.createElement( 'div' );
	Morebits.status.init( root );
	Window.setContent( root );
	Window.display();
};

Twinkle.batchprotect.currentProtectCounter = 0;
Twinkle.batchprotect.currentprotector = 0;
Twinkle.batchprotect.callback.evaluate = function twinklebatchprotectCallbackEvaluate(event) {
	wgPageName = mw.config.get('wgPageName').replace( /_/g, ' ' ); // for queen/king/whatever and country!
	var pages = event.target.getChecked( 'pages' );
	var reason = event.target.reason.value;
	var create = event.target.create.value;
	var edit = event.target.edit.value;
	var cascade = event.target.cascade.checked;
	var expiry = event.target.expiry.value;
	var move = event.target.move.value;
	if( ! reason ) {
		return;
	}
	Morebits.status.init( event.target );
	if( !pages ) {
		Morebits.status.error( 'Error', 'nothing to delete, aborting' );
		return;
	}

	function toCall( work ) {
		if( work.length === 0 && Twinkle.batchprotect.currentProtectCounter <= 0 ) {
			Morebits.status.info( 'work done' );
			window.clearInterval( Twinkle.batchprotect.currentprotector );
			Morebits.wiki.removeCheckpoint();
			return;
		} else if( work.length !== 0 && Twinkle.batchprotect.currentProtectCounter <= Twinkle.getPref('batchProtectMinCutOff') ) {
			var pages = work.shift();
			Twinkle.batchprotect.currentProtectCounter += pages.length;
			for( var i = 0; i < pages.length; ++i ) {
				var page = pages[i];
				var query = {
					'action': 'query',
					'titles': page
				};
				var wikipedia_api = new Morebits.wiki.api( 'Checking if page ' + page + ' exists', query, Twinkle.batchprotect.callbacks.main );
				wikipedia_api.params = { page:page, reason:reason, move: move, edit: edit, create: create, expiry: expiry, cascade: cascade };
				wikipedia_api.post();
			}
		}
	}
	var work = pages.chunk( Twinkle.getPref('batchProtectChunks') );
	Morebits.wiki.addCheckpoint();
	Twinkle.batchprotect.currentprotector = window.setInterval( toCall, 1000, work );
};

Twinkle.batchprotect.callbacks = {
	main: function( self ) {
		var xmlDoc = self.responseXML;
		var normal = xmlDoc.evaluate( '//normalized/n/@to', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
		if( normal ) {
			self.params.page = normal;
		}

		var query = { 
			'title': self.params.page, 
			'action': 'protect'
		};
		var wikipedia_wiki = new Morebits.wiki.wiki( 'Protecting page ' + self.params.page, query, Twinkle.batchprotect.callbacks.protectPage, function( self ) { 
				--Twinkle.batchprotect.currentProtectCounter;
				var link = document.createElement( 'a' );
				link.setAttribute( 'href', mw.config.get('wgArticlePath').replace( '$1', self.query.title ) );
				link.setAttribute( 'title', self.query.title );
				link.appendChild( document.createTextNode( self.query.title ) );
				self.statelem.info( [ 'completed (' , link , ')' ] );

			} );
		wikipedia_wiki.params = self.params;
		wikipedia_wiki.followRedirect = false;
		wikipedia_wiki.get();		
	},
	protectPage: function( self ) {
		var form  = self.responseXML.getElementById( 'mw-Protect-Form' );
		var postData = {
			'wpEditToken': form.wpEditToken.value,
			'mwProtect-level-edit': self.params.edit,
			'wpProtectExpirySelection-edit': self.params.expiry != 'indefinite' ? 'othertime' : 'indefinite',
			'mwProtect-expiry-edit': self.params.expiry != 'indefinite' ? self.params.expiry : undefined,
			'mwProtect-level-move': self.params.move,
			'wpProtectExpirySelection-move': self.params.expiry != 'indefinite' ? 'othertime' : 'indefinite',
			'mwProtect-expiry-move': self.params.expiry != 'indefinite' ? self.params.expiry : undefined,
			'mwProtect-cascade': self.params.cascade ? '' : undefined,
			'mwProtectWatch': form.mwProtectWatch.checked ? '' : undefined,
			'wpProtectReasonSelection': 'other',
			'mwProtect-reason': self.params.reason + Twinkle.getPref('protectionSummaryAd')
		};

		self.post( postData );
	}
};

/*
 ****************************************
 *** twinklebatchundelete.js: Batch undelete module
 ****************************************
 * Mode of invocation:     Tab ("Und-batch")
 * Active on:              Existing and non-existing user pages (??? why?)
 * Config directives in:   TwinkleConfig
 */


Twinkle.batchundelete = function twinklebatchundelete() {
	if( mw.config.get('wgNamespaceNumber') != mw.config.get("wgNamespaceIds").USER ) {
		return;
	}
	if( Morebits.userIsInGroup( 'sysop' ) ) {
		twAddPortletLink(Twinkle.batchundelete.callback, "Und-batch", "tw-batch-undel", "Recuperează tot");
	}
};

Twinkle.batchundelete.callback = function twinklebatchundeleteCallback() {
	var Window = new Morebits.simpleWindow( 800, 400 );
	var form = new Morebits.quickForm( Twinkle.batchundelete.callback.evaluate );
	form.append( {
			type: 'textarea',
			name: 'reason',
			label: 'Reason: '
		} );

	var query = {
		'action': 'query',
		'generator': 'links',
		'titles': mw.config.get('wgPageName'),
		'gpllimit' : Twinkle.getPref('batchMax') // the max for sysops
	};
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing pages', query, function( self ) {
			var xmlDoc = self.responseXML;
			var snapshot = xmlDoc.evaluate('//page[@missing]', xmlDoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );
			var list = [];
			for ( var i = 0; i < snapshot.snapshotLength; ++i ) {
				var object = snapshot.snapshotItem(i);
				var page = xmlDoc.evaluate( '@title', object, null, XPathResult.STRING_TYPE, null ).stringValue;
				list.push( {label:page, value:page, checked: true });
			}
			self.params.form.append( {
					type: 'checkbox',
					name: 'pages',
					list: list
				}
			);
			self.params.form.append( { type:'submit' } );

			var result = self.params.form.render();
			self.params.Window.setContent( result );


		}  );
	wikipedia_api.params = { form:form, Window:Window };
	wikipedia_api.post();
	var root = document.createElement( 'div' );
	Morebits.status.init( root );
	Window.setContent( root );
	Window.display();
};
Twinkle.batchundelete.currentUndeleteCounter = 0;
Twinkle.batchundelete.currentundeletor = 0;
Twinkle.batchundelete.callback.evaluate = function( event ) {
	Morebits.wiki.actionCompleted.notice = 'Status';
	Morebits.wiki.actionCompleted.postfix = 'batch undeletion is now completed';

	var pages = event.target.getChecked( 'pages' );
	var reason = event.target.reason.value;
	if( ! reason ) {
		return;
	}
	Morebits.status.init( event.target );

	if( !pages ) {
		Morebits.status.error( 'Error', 'nothing to undelete, aborting' );
		return;
	}

	var work = pages.chunk( Twinkle.getPref('batchUndeleteChunks') );
	Morebits.wiki.addCheckpoint();
	Twinkle.batchundelete.currentundeletor = window.setInterval( Twinkle.batchundelete.callbacks.main, 1000, work, reason );
};

Twinkle.batchundelete.callbacks = {
	main: function( work, reason ) {
		if( work.length === 0 && Twinkle.batchundelete.currentUndeleteCounter <= 0 ) {
			Morebits.status.info( 'work done' );
			window.clearInterval( Twinkle.batchundelete.currentundeletor );
			Morebits.wiki.removeCheckpoint();
			return;
		} else if( work.length !== 0 && Twinkle.batchundelete.currentUndeleteCounter <= Twinkle.getPref('batchUndeleteMinCutOff') ) {
			var pages = work.shift();
			Twinkle.batchundelete.currentUndeleteCounter += pages.length;
			for( var i = 0; i < pages.length; ++i ) {
				var title = pages[i];
				var query = { 
					'title': 'Special:Undelete',
					'target': title,
					'action': 'submit'
				};
				var wikipedia_wiki = new Morebits.wiki.wiki( "Recuperez " + title, query, Twinkle.batchundelete.callbacks.undeletePage, function( self ) { 
						--Twinkle.batchundelete.currentUndeleteCounter;
						var link = document.createElement( 'a' );
						link.setAttribute( 'href', mw.util.getUrl(self.params.title) );
						link.setAttribute( 'title', self.params.title );
						link.appendChild( document.createTextNode(self.params.title) );
						self.statelem.info( ['completed (',link,')'] );

					});
				wikipedia_wiki.params = { title:title, reason: reason };
				wikipedia_wiki.get();

			}
		}
	},
	undeletePage: function( self ) {
		var form = self.responseXML.getElementById('undelete');
		var postData = {
			'wpComment': self.params.reason + '.' +  Twinkle.getPref('deletionSummaryAd'),
			'target': self.params.image,
			'wpEditToken': form.wpEditToken.value,
			'restore': 1
		};
		self.post( postData );

	}
};

/*
****************************************
*** twinklecloser.js: AFD/AFC closer module
****************************************
* Mode of invocation:     Link on AFD subpages (including daily log pages) and AFC daily log pages
* Active on:              The aforementioned pages
* Config directives in:   TwinkleConfig
*/

Twinkle.closer = function twinklecloser() {
	var closeable = false;
	var type;
	if( /Wikipedia:Articles_for_creation\/\d{4}-\d{2}-\d{2}/.test(mw.config.get('wgPageName')) ) {
		closeable = true;
		type = 'afc';
	} else if(  /Wikipedia:Pagini_de_\u0219ters/.test(mw.config.get('wgPageName')) ) {
		closeable = true;
		type = 'afd';
	}

	if( closeable ) {
		Twinkle.closer.mark( type );
	}
};

Twinkle.closer.mark = function twinklecloserMark( type ) {
	var sections;
	switch( type ) {
	case 'afc':
		sections = $('h3:has(span.editsection)');
		sections.each(function(index, section) {
			var query = new Morebits.queryString($(this).find('span.editsection a').attr('href').split( '?', 2 )[1]);
			var section_number = query.get('section');
			var closelink = $('<a/>', {
				'text': '[închide] ',
				'click': function(){Twinkle.closer.actions.afc(section_number);},
				'class': 'twinkle-closer-link twinkle-closer-link-afc',
				'css': { 'color': '#449922'	}
			}).prependTo(this);
		});
		break;
	case 'afd':
		sections = $('h3:has(span.mw-editsection)');
		sections.each(function(index, section) {
		var $a = $(this).find('span.mw-editsection a');
	    var query = new Morebits.queryString($a.attr('href').split( '?', 2 )[1]);
	    var section_number = query.get('section');
	    var page = query.get('title').replace(/_/g, ' ');
	    var closelink = $('<a/>', {
				'text': '[închide] ',
				'click': function(){Twinkle.closer.actions.afd(section_number, page);},
				'class': 'twinkle-closer-link twinkle-closer-link-afd',
				'css': { 'color': '#449922'	}
			}).prependTo(this);
		});
		break;
	default:
		alert("Twinkle.closer.mark: tip de închidere necunoscut " + type);
		break;
	}
};

Twinkle.closer.actions = {
	afc: function twinklecloserActionsAfc( section ) {
		var Window = new Morebits.simpleWindow( 800, 400 );
		Window.setTitle( "Close AFC" );
		Window.setScriptName( "Twinkle" );
		Window.addFooterLink( "AFC reviewing instructions", "WP:AFCR" );
		Window.addFooterLink( "Twinkle help", "WP:TW/DOC#closer-afc" );

		var form = new Morebits.quickForm( Twinkle.closer.callbacks.afc.evaluate );
		form.append ( {
			label: 'Action: ',
			type: 'select',
			name: 'type',
			event: Twinkle.closer.callbacks.afc.submenu,
			list: [
				{
					label: 'Aprobat',
					value: 'approved'
				},
				{
					label: 'Refuzat',
					value: 'denied'
				},
				{
					label: 'Arhivat',
					value: 'archive'
				}
			]
		});
		form.append( {
			type: 'div',
			id: 'work_area'
		} );
		form.append( {
			type: 'hidden',
			name: 'section',
			value: section
		} );
		form.append( {
			type: 'hidden',
			name: 'page',
			value: page
		} );
		form.append( { type:'submit' } );

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

		// We must init the
		var evt = document.createEvent( "Event" );
		evt.initEvent( 'change', true, true );
		result.type.dispatchEvent( evt );
	},
	afd: function twinklecloserActionsAfd( section, page ) {
		var Window = new Morebits.simpleWindow( 800, 400 );
		Window.setTitle( "Închidere propunere de ștergere" );
		Window.setScriptName( "Twinkle" );
		Window.addFooterLink( "Instrucțiuni pentru închiderea discuțiilor de ștergere", ":en:Wikipedia:Articles for deletion/Administrator instructions" );
		Window.addFooterLink( "Twinkle help", ":en:WP:TW/DOC#closer-afd" );

		var form = new Morebits.quickForm( Twinkle.closer.callbacks.afd.evaluate );
		form.append ( {
			label: 'Acțiune: ',
 			type: 'radio',
 			name: 'closuretype',
			list: [
 				{
 					label: 'Păstrare',
 					value: 'keep'
				},
				{
					label: 'Lipsă consens',
 					value: 'no consensus'
 				},
 				{
 					label: 'Unire',
 					value: 'merge'
 				},
 				{
 					label: 'Redirecționare',
 					value: 'redirect',
 					subgroup: {
 						type: 'input',
						name: 'target',
 						label: 'Către: ',
						tooltip: 'numele paginii către care se redirecționează'
 					}

				},
				{
 					label: 'Ștergere',
 					value: 'delete',
					subgroup: {
 						type: 'checkbox',
						list: [
							{
								label: 'Ștergem chiar acum? ',
								value: 'delete',
								name: 'del',
								tooltop: 'dacă să ștergem pagina pe loc',
 								checked: true
							}
						]
 					}
				}
			]
		});
		form.append( {
			type: 'textarea',
			name: 'reason',
			label: 'Motiv:'
		} );

		form.append( {
			type: 'input',
			name: 'affected_page',
			label: 'Pagină afectată: ',
			value: page.replace( /[^\/]*?\/(.*?)($|(\s+\(\d+?\)))/, "$1" )
		} );

		form.append( {
			type: 'div',
			id: 'work_area'
		} );

		form.append( {
			type: 'hidden',
			name: 'section',
			value: section
		} );
		form.append( {
			type: 'hidden',
			name: 'page',
			value: page
		} );
		form.append( { type:'submit' } );
		var result = form.render();
		Window.setContent( result );
		Window.display();
	}
};

Twinkle.closer.callbacks = {
	afc: {
		submenu: function(e) {
			var value = e.target.value;
			var root = e.target.form;
			var old_area = document.getElementById( 'work_area' );
			var work_area = null;
			switch( value ) {
			case 'archive':
				work_area = new Morebits.quickForm.element( {
					type: 'div',
					id: 'work_area'
				} );

				work_area.append( {
					type: 'checkbox',
					name: 'approved',
					list: [
						{
							label: 'Aprobat ',
							value: 'approved'
						}
					]
				} );

				work_area = work_area.render();
				old_area.parentNode.replaceChild( work_area, old_area );
				break;
			case 'approved':
				work_area = new Morebits.quickForm.element( {
					type: 'div',
					id: 'work_area'
				} );

				work_area.append( {
					type: 'input',
					name: 'article',
					label: 'Articol ',
					tooltop: 'Lăsați gol dacă articolul a fost creat după cum s-a specificat'
				} );

				work_area = work_area.render();
				old_area.parentNode.replaceChild( work_area, old_area );
				break;
			case 'denied':
				work_area = new Morebits.quickForm.element( {
					type: 'div',
					id: 'work_area'
				} );

				work_area.append( {
					type: 'select',
					name: 'reason',
					label: 'Motiv ',
					list: [
						{
							label:'v',
							value:'v'
						},
						{
							label:'bio',
							value:'bio'
						},
						{
							label:'nn',
							value:'nn'
						},
						{
							label:'web',
							value:'web'
						},
						{
							label:'corp',
							value:'corp'
						},
						{
							label:'music',
							value:'music'
						},
						{
							label:'dict',
							value:'dict'
						},
						{
							label:'context',
							value:'context'
						},
						{
							label:'blank',
							value:'blank'
						},
						{
							label:'neo',
							value:'neo'
						},
						{
							label:'joke',
							value:'joke'
						},
						{
							label:'lang',
							value:'lang'
						},
						{
							label:'blp',
							value:'blp'
						},
						{
							label:'npov',
							value:'npov'
						},
						{
							label:'not',
							value:'not'
						}
					]
				} );
				work_area = work_area.render();
				old_area.parentNode.replaceChild( work_area, old_area );
				break;
			default:
				alert("Twinkle.closer.callbacks.afc.submenu: unknown outcome " + value);
				break;
			}
		},
		evaluate: function(e) {
			var form = e.target;
			var type = form.type.value;
			var section = form.section.value;
			var params = { type: type };
			switch( type ) {
			case 'approved':
				var article = form.article.value;
				params.tag = '{{subst:afc accept' + ( article ? '|' + article : '' ) + '}}';
				break;
			case 'denied':
				var reason = form.reason.value;
				params.tag = '{{subst:afc ' + reason + '}}';
				break;
			case 'archive':
				var approved = form.approved.checked;
				params.top = '{{subst:afc top' + ( approved ? '|approved' : '' ) + '}}';
				params.bottom = '{{subst:afc b}}';
				break;
			default:
				alert("Twinkle.closer.callbacks.afc.evaluate: unknown outcome " + type);
				break;
			}

			Morebits.simpleWindow.setButtonsEnabled( false );
			Morebits.status.init( form );
			var page = Morebits.wiki.page(mw.config.get('wgPageName'), "Processing");
			page.setPageSection(section);
			page.setCallbackParameters(params);
			page.load(Twinkle.closer.callbacks.afc.edit);
		},
		edit: function( pageobj ) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();
			var summary;

			switch( params.type ) {
			case 'approved':
				text += params.tag + '~~~~';
				summary = 'Approving article.';
				break;
			case 'denied':
				text += params.tag + '~~~~';
				summary = 'Denying article.';
				break;
			case 'archive':
				text = text.replace( /^(==.*?==)\n/, "$1\n" + params.top  );
				text += params.bottom;
				summary = 'Archiving.';
				break;
			default:
				alert("Twinkle.closer.callbacks.afc.edit: unknown outcome " + params.type);
				break;
			}
			pageobj.setPageText(text);
			pageobj.setEditSummary(summary + Twinkle.getPref('summaryAd'));
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		}
	},
	afd: {
		submenu: function(e) {
			var value = e.target.value;
			var root = e.target.form;
			var old_area = document.getElementById( 'work_area' );
			var	work_area = new Morebits.quickForm.element( {
				type: 'div',
				id: 'work_area'
			} );
			switch( value ) {
			case 'keep':
			case 'no consensus':
				// nothing
				break;
			case 'redirect':
				work_area.append( {
					type: 'input',
					name: 'target',
					label: 'Către: ',
					tooltip: 'numele paginii către care se face redirecționarea'
				} );
				break;
			case 'merge':
				// merge must be done manually
				break;
			case 'delete':
				work_area.append( {
					type: 'checkbox',
					list: [
						{
							label: 'Ștergem? ',
							value: 'delete',
							name: 'del',
							tooltop: 'if we should delete the page on the fly',
							checked: true
						}
					]
				} );
				break;
			default:
				alert("Twinkle.closer.callbacks.afd.submenu: unknown outcome " + value);
				break;
			}

			work_area = work_area.render();
			old_area.parentNode.replaceChild( work_area, old_area );
		},
		evaluate: function(e) {
			var form = e.target;
			var reason = form.reason.value;
			var type;
			for (var i = 0; i < form.closuretype.length; i++) {
			        if (form.closuretype.item(i).checked) {
			                 type = form.closuretype.item(i).value;
 			        }
			}

			var section = form.section.value;
			var page = form.page.value;

			var affected_page = form.affected_page.value;
			var params = { type: type, page: page, reason: reason, affected_page: affected_page };
			var label, wp_page;
			switch( type ) {
			case 'keep':
				label = "Păstrare";
				break;
			case 'no consensus':
				label = "Fără consens";
				break;
			case 'redirect':
				label = "Redirecționare";
				var target = form.target.value;
				break;
			case 'merge':
				label = "Unire";
				break;
			case 'delete':
				label = "Ștergere";
				var del = form.del.checked;
				break;
			default:
				alert("Twinkle.closer.callbacks.afd.evaluate: unknown outcome " + type);
				break;
			}

			params.label = label;

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

			if( type === 'delete' ) {
				if( del ) {
					// Start by purging redirect
					var query = {
						'action': 'query',
						'list': 'backlinks',
						'blfilterredir': 'redirects',
						'bltitle': affected_page,
						'bllimit': 5000
					};
					var wikipedia_api = new Morebits.wiki.api( 'Caut redirecționări', query, Twinkle.closer.callbacks.afd.deleteRedirectsMain );
					wikipedia_api.params = params;
					wikipedia_api.post();

					// and now, delete!

					wp_page = new Morebits.wiki.page(affected_page, 'Șterg pagina');
					wp_page.setEditSummary("Șters în urma discuției (vezi [[" + params.page + "]])." + Twinkle.getPref('deletionSummaryAd'));
					wp_page.deletePage();
				}

			} else if( type === 'keep' ) {
				var titleSplit = affected_page.split(':');
				var gapnamespace = mw.config.get("wgNamespaceIds")[titleSplit[0].toLowerCase()];
				var talkNS, affected_page_title;
				if ( titleSplit.length < 2 || typeof(gapnamespace) === 'undefined' )
				{
					gapnamespace = 0;
					affected_page_title = affected_page;
				} else {
					affected_page_title = titleSplit[1];
					for (var i = 2; i < titleSplit.length; i++) {
						affected_page_title = affected_page_title + ':' + titleSplit[i];
					}
				}
				talkNS = Morebits.wikipedia.namespacesFriendly[gapnamespace + 1];
				
				var talk_page = new Morebits.wiki.page(talkNS + ':' + affected_page_title);
				params.afd_title = page.substr(page.indexOf('/') + 1);
				talk_page.setCallbackParameters(params);
				talk_page.load(Twinkle.closer.callbacks.afd.markTalkPageOfKeptPage);

				wp_page = new Morebits.wiki.page(affected_page, "Elimin formatul {{Șterge}} din pagină");
				wp_page.setCallbackParameters(params);
				wp_page.load(Twinkle.closer.callbacks.afd.removeDeleteTemplate);
			}				

			wp_page = new Morebits.wiki.page(page, "Actualizez pagina de discuție");
			wp_page.setPageSection(section);
			wp_page.setCallbackParameters(params);
			wp_page.load(Twinkle.closer.callbacks.afd.edit);
		},
		markTalkPageOfKeptPage: function ( pageobj ) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			text = "{{Păstrat|1=" + params.afd_title + "}}\n" + text;
			pageobj.setPageText(text);
			pageobj.setEditSummary("Pagină păstrată în urma discuției de la [[" + params.page + "]]." + Twinkle.getPref('deletionSummaryAd'));
			pageobj.save();
		},
		removeDeleteTemplate: function ( pageobj ) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			text = text.replace(/\{\{\u0219terge\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, "");
			pageobj.setPageText(text);
			pageobj.setEditSummary("Pagină păstrată în urma discuției de la [[" + params.page + "]]." + Twinkle.getPref('deletionSummaryAd'));
			pageobj.save();
		},
		deleteRedirectsMain: function( self ) {
			var $doc = $(self.responseXML);
			$doc.find("backlinks bl").each(function(){
				var title = $(this).attr('title');
				var page = new Morebits.wiki.page(title, "șterg pagina de redirecționare " + title);
				page.setEditSummary("Șters rapid conform ([[WP:CȘR#G8|CȘR G8]]), redirect spre pagină ștearsă \"" + self.params.affected_page + "\"." + Twinkle.getPref('deletionSummaryAd'));
				page.deletePage();
			});
		},
		edit: function( pageobj ) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			pageobj.setEditSummary( "Închid discuția, rezultatul a fost \"" + params.label + "\"" +  Twinkle.getPref('summaryAd') );
			text = text.replace(/\{\{\s*Rezumat propunere de \u0219tergere\|start\=/ig, "{{Rezumat propunere de ștergere|rezultat=" + params.label + "|start=");
			text = text.replace(/\|end\=.*\}\}/ig, "|end={{subst:#timel:j F Y}} }}");
			pageobj.setPageText(text + "\n\n'''Discuție încheiată'''." + params.reason + "~~~~\n" + "</div>");
			pageobj.save();
		}
	}
};

/*
 ****************************************
 *** twinkleconfig.js: Preferences module
 ****************************************
 * Mode of invocation:     Adds configuration form to Wikipedia:Twinkle/Preferences and user 
                           subpages named "/Twinkle preferences", and adds ad box to the top of user 
                           subpages belonging to the currently logged-in user which end in '.js'
 * Active on:              What I just said.  Yeah.
 * Config directives in:   TwinkleConfig

 I, [[User:This, that and the other]], originally wrote this.  If the code is misbehaving, or you have any
 questions, don't hesitate to ask me.  (This doesn't at all imply [[WP:OWN]]ership - it's just meant to
 point you in the right direction.)  -- TTO
 */


Twinkle.config = {};

Twinkle.config.commonEnums = {
	watchlist: { yes: "Urmărește", no: "Nu urmări", "default": "Respectă preferințele site-ului" },
	talkPageMode: { window: "Într-o fereastră, în locul altei discuții", tab: "Într-un tab nou", blank: "Într-o altă fereastră" }
};

Twinkle.config.commonSets = {
	csdCriteria: {
		db: "Explicație specială ({{șr}})",
		g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12",
		a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
		u1: "U1", u2: "U2", u3: "U3", u4: "U4",
		f1: "F1", f2: "F2", f3: "F3", f7: "F7", f8: "F8", f9: "F9", f10: "F10",
		//c1: "C1",
		//t2: "T2", t3: "T3",
		r2: "R2", r3: "R3",
		//p1: "P1", p2: "P2"  // db-multiple is not listed here because it is treated differently within twinklespeedy
	},
	csdCriteriaDisplayOrder: [
		"db",
		"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12",
		"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
		"u1", "u2", "u3", "u4",
		"f1", "f2", "f3", "f7", "f8", "f9", "f10",
		//"c1",
		//"t2", "t3",
		"r2", "r3",
		//"p1", "p2"
	],
	csdAndDICriteria: {
		db: "Motivație specială ({{șr}})",
		g1: "G1", g2: "G2", g3: "G3", g4: "G4", g5: "G5", g6: "G6", g7: "G7", g8: "G8", g10: "G10", g11: "G11", g12: "G12",
		a1: "A1", a2: "A2", a3: "A3", a5: "A5", a7: "A7", a9: "A9", a10: "A10", a11: "A11",
		u1: "U1", u2: "U2", u3: "U3", u4: "U4",
		f1: "F1", f2: "F2", f3: "F3", f4: "F4", f5: "F5", f6: "F6", f7: "F7", f8: "F8", f9: "F9", f10: "F10", f11: "F11",
		//c1: "C1",
		//t2: "T2", t3: "T3",
		r2: "R2", r3: "R3",
		//p1: "P1", p2: "P2"
	},
	csdAndDICriteriaDisplayOrder: [
		"db",
		"g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g10", "g11", "g12",
		"a1", "a2", "a3", "a5", "a7", "a9", "a10", "a11",
		"u1", "u2", "u3",
		"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11",
		//"c1",
		//"t2", "t3",
		"r2", "r3",
		//"p1", "p2"
	],
	namespacesNoSpecial: {
		"0": "Articol",
		"1": "Discuție (articol)",
		"2": "Utilizator",
		"3": "Discuție Utilizator",
		"4": "Wikipedia",
		"5": "Discuție Wikipedia",
		"6": "Fișier",
		"7": "Discuție Fișier",
		"8": "MediaWiki",
		"9": "Discuție MediaWiki",
		"10": "Format",
		"11": "Discuție Format",
		"12": "Ajutor",
		"13": "Discuție Ajutor",
		"14": "Categorie",
		"15": "Discuție Categorie",
		"100": "Portal",
		"101": "Discuție Portal",
		"108": "Cod",
		"109": "Discuție Cod",
		"110": "Carte",
		"111": "Discuție Carte"
	}
};

/**
 * Section entry format:
 *
 * {
 *   title: <human-readable section title>,
 *   adminOnly: <true for admin-only sections>,
 *   hidden: <true for advanced preferences that rarely need to be changed - they can still be modified by manually editing twinkleoptions.js>,
 *   inFriendlyConfig: <true for preferences located under FriendlyConfig rather than TwinkleConfig>,
 *   preferences: [
 *     {
 *       name: <TwinkleConfig property name>,
 *       label: <human-readable short description - used as a form label>,
 *       helptip: <(optional) human-readable text (using valid HTML) that complements the description, like limits, warnings, etc.>
 *       adminOnly: <true for admin-only preferences>,
 *       type: <string|boolean|integer|enum|set|customList> (customList stores an array of JSON objects { value, label }),
 *       enumValues: <for type = "enum": a JSON object where the keys are the internal names and the values are human-readable strings>,
 *       setValues: <for type = "set": a JSON object where the keys are the internal names and the values are human-readable strings>,
 *       setDisplayOrder: <(optional) for type = "set": an array containing the keys of setValues (as strings) in the order that they are displayed>,
 *       customListValueTitle: <for type = "customList": the heading for the left "value" column in the custom list editor>,
 *       customListLabelTitle: <for type = "customList": the heading for the right "label" column in the custom list editor>
 *     },
 *     . . .
 *   ]
 * },
 * . . .
 *
 */

Twinkle.config.sections = [
{
	title: "General",
	preferences: [
		// TwinkleConfig.summaryAd (string)
		// Text to be appended to the edit summary of edits made using Twinkle
		{
			name: "summaryAd",
			label: "\"Reclamă\" de adăugat la sumarul modificărilor făcute cu Twinkle",
			helptip: "Trebuie să înceapă cu spațiu și să fie scurt.",
			type: "string"
		},

		// TwinkleConfig.deletionSummaryAd (string)
		// Text to be appended to the edit summary of deletions made using Twinkle
		{
			name: "deletionSummaryAd",
			label: "Text adăugat la sumarul ștergerilor",
			helptip: "În mod normal la fel ca mai sus.",
			adminOnly: true,
			type: "string"
		},

		// TwinkleConfig.protectionSummaryAd (string)
		// Text to be appended to the edit summary of page protections made using Twinkle
		{
			name: "protectionSummaryAd",
			label: "Text adăugat la sumarul protejărilor de pagină",
			helptip: "În mod normal la fel ca mai sus.",
			adminOnly: true,
			type: "string"
		},

		// TwinkleConfig.userTalkPageMode may take arguments:
		// 'window': open a new window, remember the opened window
		// 'tab': opens in a new tab, if possible.
		// 'blank': force open in a new window, even if such a window exists
		{
			name: "userTalkPageMode",
			label: "Când deschid o pagină de discuție a utilizatorului, o deschid",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.talkPageMode
		},

		// TwinkleConfig.dialogLargeFont (boolean)
		{
			name: "dialogLargeFont",
			label: "Folosește text mai mare în ferestrele de dialog Twinkle",
			type: "boolean"
		}
	]
},

{
	title: "ștergeri de imagini",
	preferences: [
		// TwinkleConfig.notifyUserOnDeli (boolean)
		// If the user should be notified after placing a file deletion tag
		{
			name: "notifyUserOnDeli",
			label: "Bifează implicit caseta \"notifică uploaderul\"",
			type: "boolean"
		},

		// TwinkleConfig.deliWatchPage (string)
		// The watchlist setting of the page tagged for deletion. Either "yes", "no", or "default". Default is "default" (Duh).
		{
			name: "deliWatchPage",
			label: "Adaugă pagina imaginii etichetate în lista de pagini urmărite",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		},

		// TwinkleConfig.deliWatchUser (string)
		// The watchlist setting of the user talk page if a notification is placed. Either "yes", "no", or "default". Default is "default" (Duh).
		{
			name: "deliWatchUser",
			label: "Adaugă pagina de discuție a uploaderului notificat la lista de pagini urmărite",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		}
	]
},

{
	title: "Reveniri",  // twinklefluff module
	preferences: [
		// TwinkleConfig.openTalkPage (array)
		// What types of actions that should result in opening of talk page
		{
			name: "openTalkPage",
			label: "Deschide pagina de discuție a utilizatorului după următoarele reveniri:",
			type: "set",
			setValues: { agf: "Revenire BC", norm: "Revenire normală", vand: "Revenire vandalism", torev: "\"Restaurează versiunea\"" }
		},

		// TwinkleConfig.openTalkPageOnAutoRevert (bool)
		// Defines if talk page should be opened when calling revert from contrib page, because from there, actions may be multiple, and opening talk page not suitable. If set to true, openTalkPage defines then if talk page will be opened.
		{
			name: "openTalkPageOnAutoRevert",
			label: "Deschide pagina de discuție a utilizatorului când se face revenire din lista sa de contribuții",
			helptip: "Adesea, e cazul să faceți reveniri pe mai multe pagini din lista de contribuții ale unui vandal, deci poate nu vreți să deschideți pagina de discuții mereu și mereu.",
			type: "boolean"
		},

		// TwinkleConfig.markRevertedPagesAsMinor (array)
		// What types of actions that should result in marking edit as minor
		{
			name: "markRevertedPagesAsMinor",
			label: "Marchează ca minore următoarele tipuri de reveniri",
			type: "set",
			setValues: { agf: "Revenire BC", norm: "Revenire normală", vand: "Revenire vandalism", torev: "\"Restaurează versiunea\"" }
		},

		// TwinkleConfig.watchRevertedPages (array)
		// What types of actions that should result in forced addition to watchlist
		{
			name: "watchRevertedPages",
			label: "Adaugă la lista de pagini urmărite cele în care s-a făcut următoarele reveniri",
			type: "set",
			setValues: { agf: "Revenire BC", norm: "Revenire normală", vand: "Revenire vandalism", torev: "\"Restaurează versiunea\"" }
		},

		// TwinkleConfig.offerReasonOnNormalRevert (boolean)
		// If to offer a prompt for extra summary reason for normal reverts, default to true
		{
			name: "offerReasonOnNormalRevert",
			label: "Cere motiv la reveniri normale",
			helptip: "Revenirile \"normale\" sunt cele invocate cu linkul de [revenire] din mijloc.",
			type: "boolean"
		},

		{
			name: "confirmOnFluff",
			label: "Mesaj de confirmare înainte de revenire",
			helptip: "Pentru utilizatorii unor dispozitive cu touch-screen, și pentru cei adesea nehotărâți.",
			type: "boolean"
		},

		// TwinkleConfig.showRollbackLinks (array)
		// Where Twinkle should show rollback links (diff, others, mine, contribs)
		// Note from TTO: |contribs| seems to be equal to |others| + |mine|, i.e. redundant, so I left it out heres
		{
			name: "showRollbackLinks",
			label: "Arată legături de revenire pe următoarele pagini",
			type: "set",
			setValues: { diff: "Pagini cu diffuri", others: "Liste de contribuții ale altor utilizatori", mine: "Contribuțiile mele" }
		}
	]
},

{
	title: "Etichetarea adreselor IP partajate",
	inFriendlyConfig: true,
	preferences: [
		{
			name: "markSharedIPAsMinor",
			label: "Marchează etichetarea adreselor IP partajate ca minoră",
			type: "boolean"
		}
	]
},

{
	title: "ștergere rapidă (CȘR)",
	preferences: [
		// TwinkleConfig.speedyPromptOnG7 (boolean)
		{
			name: "speedyPromptOnG7",
			label: "Cere explicații la etichetarea cu G7 (la cererea autorului)",
			type: "boolean"
		},

		// TwinkleConfig.watchSpeedyPages (array)
		// Whether to add speedy tagged pages to watchlist
		{
			name: "watchSpeedyPages",
			label: "Urmărește pagina la etichetarea cu aceste criterii",
			type: "set",
			setValues: Twinkle.config.commonSets.csdCriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder
		},

		// TwinkleConfig.markSpeedyPagesAsPatrolled (boolean)
		// If, when applying speedy template to page, to mark the page as patrolled (if the page was reached from NewPages)
		{
			name: "markSpeedyPagesAsPatrolled",
			label: "Marchează pagina ca patrulată la etichetare",
			helptip: "Există limitări tehnice care fac ca doar paginile văzute din Special:NewPages să poată fi marcate ca patrulate.",
			type: "boolean"
		},

		// TwinkleConfig.notifyUserOnSpeedyDeletionNomination (array)
		// What types of actions should result that the author of the page being notified of nomination
		{
			name: "notifyUserOnSpeedyDeletionNomination",
			label: "Notifică creatorul paginii doar la etichetarea cu aceste criterii",
			helptip: "Chiar dacă alegeți notificare din ecranul CȘR, ele vor avea  loc doar pentru criteriile selectate aici.",
			type: "set",
			setValues: Twinkle.config.commonSets.csdCriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder
		},

		// TwinkleConfig.welcomeUserOnSpeedyDeletionNotification (array of strings)
		// On what types of speedy deletion notifications shall the user be welcomed
		// with a "firstarticle" notice if his talk page has not yet been created.
		{
			name: "welcomeUserOnSpeedyDeletionNotification",
			label: "Scrie mesaj de bun venit creatorului paginii împreună cu notificarea în următoarele cazuri",
			helptip: "Mesajul de bun venit se pune doar dacă utilizatorul este notificat despre ștergere și doar dacă pagina sa de discuție este goală. Formatul utilizat este{{<a href=\"" + mw.util.getUrl("Format:Firstarticle") + "\">firstarticle</a>}}.",
			type: "set",
			setValues: Twinkle.config.commonSets.csdCriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdCriteriaDisplayOrder
		},

		// TwinkleConfig.promptForSpeedyDeletionSummary (array of strings)
		{
			name: "promptForSpeedyDeletionSummary",
			label: "Permite modificarea sumarului ștergerii în următoarele cazuri",
			adminOnly: true,
			type: "set",
			setValues: Twinkle.config.commonSets.csdAndDICriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
		},

		// TwinkleConfig.openUserTalkPageOnSpeedyDelete (array of strings)
		// What types of actions that should result user talk page to be opened when speedily deleting (admin only)
		{
			name: "openUserTalkPageOnSpeedyDelete",
			label: "Deschide pagina de discuție a utilizatorului la următoarele tipuri de ștergeri",
			adminOnly: true,
			type: "set",
			setValues: Twinkle.config.commonSets.csdAndDICriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
		},

		// TwinkleConfig.deleteTalkPageOnDelete (boolean)
		// If talk page if exists should also be deleted (CSD G8) when spedying a page (admin only)
		{
			name: "deleteTalkPageOnDelete",
			label: "Bifează implicit \"șterge și pagina de discuții\"",
			adminOnly: true,
			type: "boolean"
		},

		// TwinkleConfig.deleteSysopDefaultToTag (boolean)
		// Make the CSD screen default to "tag" instead of "delete" (admin only)
		{
			name: "deleteSysopDefaultToTag",
			label: "Etichetează implicit pentru ștergere rapidă, nu șterge direct",
			adminOnly: true,
			type: "boolean"
		},

		// TwinkleConfig.speedyWindowWidth (integer)
		// Defines the width of the Twinkle SD window in pixels
		{
			name: "speedyWindowWidth",
			label: "Lățimea ferestrei de ștergeri rapide (pixeli)",
			type: "integer"
		},

		// TwinkleConfig.speedyWindowWidth (integer)
		// Defines the width of the Twinkle SD window in pixels
		{
			name: "speedyWindowHeight",
			label: "Înălțimea ferestrei de ștergeri rapide (pixeli)",
			helptip: "Dacă aveți monitor mare, v-ar conveni o valoare mai mare.",
			type: "integer"
		},

		{
			name: "logSpeedyNominations",
			label: "Păstrează un jurnal al propunerilor de ștergere rapidă",
			helptip: "Cei care nu sunt administratori nu-și pot vedea contribuțiile șterse, așa că jurnalul oferă o modalitate de a urmări paginile propuse pentru ștergere rapidă. și fișierele etichetate se adaugă la acest jurnal.",
			type: "boolean"
		},
		{
			name: "speedyLogPageName",
			label: "Păstrează jurnalul propunerilor de ștergere rapidă la pagina:",
			helptip: "i.e. Utilizator:<i>username</i>/<i>numele subpaginii</i>. Funcționează doar dacă e activat jurnalul.",
			type: "string"
		},
		{
			name: "noLogOnSpeedyNomination",
			label: "Nu salva în jurnal în cazurile următoare",
			type: "set",
			setValues: Twinkle.config.commonSets.csdAndDICriteria,
			setDisplayOrder: Twinkle.config.commonSets.csdAndDICriteriaDisplayOrder
		}
	]
},

{
	title: "Tag",
	inFriendlyConfig: true,
	preferences: [
		{
			name: "groupByDefault",
			label: "Bifați automat \"grupează în {{probleme}}\"",
			type: "boolean"
		},
		{
			name: "watchTaggedPages",
			label: "Adaugă paginile etichetate la lista de pagini urmărite",
			type: "boolean"
		},
		{
			name: "markTaggedPagesAsMinor",
			label: "Marchează etichetările ca modificări minore",
			type: "boolean"
		},
		{
			name: "markTaggedPagesAsPatrolled",
			label: "Marchează etichetările ca patrulate",
			helptip: "Din motive tehnice, se marchează ca patrulate doar cele din Special:NewPages.",
			type: "boolean"
		},
		{
			name: "customTagList",
			label: "Etichete de întreținere suplimentare",
			helptip: "Apar ca opțiuni suplimentare la lista de etichete. De exemplu, puteți adăuga etichetele de întreținere nesuportate încă de Twinkle.",
			type: "customList",
			customListValueTitle: "Numele formatului (fără acolade)",
			customListLabelTitle: "Text de afișat în dialogul de bun venit"
		}
	]
},

{
	title: "Răspuns rapid",
	inFriendlyConfig: true,
	preferences: [
		{
			name: "markTalkbackAsMinor",
			label: "Marchează răspunsurile ca modificări minore",
			type: "boolean"
		},
		{
			name: "insertTalkbackSignature",
			label: "Semnează răspunsurile",
			type: "boolean"
		},
		{
			name: "talkbackHeading",
			label: "Titlu de secțiune pentru răspunsuri",
			type: "string"
		},
		{
			name: "adminNoticeHeading",
			label: "Titlu de secțiune pentru notificări legate de avizierul administratorilor",
			type: "string"
		}
	]
},

{
	title: "Dezlegare",
	preferences: [
		// TwinkleConfig.unlinkNamespaces (array)
		// In what namespaces unlink should happen, default in 0 (article) and 100 (portal)
		{
			name: "unlinkNamespaces",
			label: "Elimină legături din spațiile de nume",
			helptip: "Evitați să selectați spațiile de nume ale discuțiilor, ca Twinkle să nu se apuce să modifice prin arhive.",
			type: "set",
			setValues: Twinkle.config.commonSets.namespacesNoSpecial
		}
	]
},

{
	title: "Warn user",
	preferences: [
		// TwinkleConfig.defaultWarningGroup (int)
		// if true, watch the page which has been dispatched an warning or notice, if false, default applies
		{
			name: "defaultWarningGroup",
			label: "Nivel implicit de avertizare",
			type: "enum",
			enumValues: { "1": "Nivelul 1", "2": "Nivelul 2", "3": "Nivelul 3", "4": "Nivelul 4", "5": "Nivelul 4im", "6": "Notificări simple", "7": "Avertismente simple", "8": "Blocare (administratori)" }
		},

		// TwinkleConfig.showSharedIPNotice may take arguments:
		// true: to show shared ip notice if an IP address
		// false: to not print the notice
		{
			name: "showSharedIPNotice",
			label: "Adaugă notificare suplimentară privind paginile de discuție ale IP-urilor partajate",
			helptip: "Se folosește {{<a href='" + mw.util.getUrl("Template:SharedIPAdvice") + "'>SharedIPAdvice</a>}}",
			type: "boolean"
		},

		// TwinkleConfig.watchWarnings (boolean)
		// if true, watch the page which has been dispatched an warning or notice, if false, default applies
		{
			name: "watchWarnings",
			label: "Adaugă pagina de discuție a utilizatorului notificat la lista de pagini urmărite",
			type: "boolean"
		},

		// TwinkleConfig.blankTalkpageOnIndefBlock (boolean)
		// if true, blank the talk page when issuing an indef block notice (per [[WP:UW#Indefinitely blocked users]])
		{
			name: "blankTalkpageOnIndefBlock",
			label: "Golește pagina de discuție a utilizatorilor blocați nelimitat",
			helptip: "Vezi <a href=\"" + mw.util.getUrl(":en:WP:UW#Indefinitely blocked users") + "\">WP:UW</a> pentru alte informații; nu se practică la Wikipedia în română.",
			adminOnly: true,
			type: "boolean"
		}
	]
},

{
	title: "Bun venit",
	inFriendlyConfig: true,
	preferences: [
		{
			name: "topWelcomes",
			label: "Pune mesajele de bun venit deasupra conținutului existent în paginile de discuție ale utilizatorilor",
			type: "boolean"
		},
		{
			name: "watchWelcomes",
			label: "Adaugă pagina de discuție a utilizatorului salutat în lista de pagini urmărite",
			helptip: "Doing so adds to the personal element of welcoming a user - you will be able to see how they are coping as a newbie, and possibly help them.",
			type: "boolean"
		},
		{
			name: "insertHeadings",
			label: "Titlu de secțiune înaintea mesajului de bun venit",
			type: "boolean"
		},
		{
			name: "welcomeHeading",
			label: "Titlu de secțiune pentru mesajul de bun venit",
			helptip: "Only has an effect if headings are enabled, and the heading is not part of the template.",
			type: "string"
		},
		{
			name: "insertUsername",
			label: "Adaugă numele de utilizator la format",
			helptip: "Some welcome templates have an opening sentence like \"Hi, I'm &lt;username&gt;. Welcome\" etc. If you turn off this option, these templates will not display your username in that way.",
			type: "boolean"
		},
		{
			name: "insertSignature",
			label: "Adaugă semnătura la mesajul de bun venit",
			helptip: "Strongly recommended.",
			type: "boolean"
		},
		{
			name: "markWelcomesAsMinor",
			label: "Marchează mesajele de bun venit ca modificări minore",
			type: "boolean"
		},
		{
			name: "maskTemplateInSummary",
			label: "Omite numele formatului de bun venit în descrierea modificării",
			helptip: "The names of some of the templates (e.g. \"welcome-anon-vandal\") may be viewed by the user as attacks, so it is better to leave them out of the edit summary",
			type: "boolean"
		},
		{
			name: "quickWelcomeMode",
			label: "Prin click pe linkul \"Bun venit\" pe o pagină diff",
			helptip: "If you choose to welcome automatically, the template you specify below will be used.",
			type: "enum",
			enumValues: { auto: "welcome automatically", norm: "prompt you to select a template" }
		},
		{
			name: "quickWelcomeTemplate",
			label: "Format de utilizat la mesajul de bun venit automat",
			helptip: "Enter the name of a welcome template, without the curly brackets. A link to the given article will be added.",
			type: "string"
		},
		{
			name: "customWelcomeList",
			label: "Alte formate de bun venit",
			helptip: "You can add other welcome templates, or user subpages that are welcome templates (prefixed with \"User:\"). Don't forget that these templates are substituted onto user talk pages.",
			type: "customList",
			customListValueTitle: "Template name (no curly brackets)",
			customListLabelTitle: "Text to show in Welcome dialog"
		}
	]
},

{
	title: "PȘ (propuneri pentru ștergere)",
	preferences: [
		// TwinkleConfig.xfdWatchPage (string)
		// The watchlist setting of the page being nominated for XfD. Either "yes" (add to watchlist), "no" (don't
		// add to watchlist), or "default" (use setting from preferences). Default is "default" (duh).
		{
			name: "xfdWatchPage",
			label: "Urmărește pagina propusă",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		},

		// TwinkleConfig.xfdWatchDiscussion (string)
		// The watchlist setting of the newly created XfD page (for those processes that create discussion pages for each nomination),
		// or the list page for the other processes.
		// Either "yes" (add to watchlist), "no" (don't add to watchlist), or "default" (use setting from preferences). Default is "default" (duh).
		{
			name: "xfdWatchDiscussion",
			label: "Urmărește pagina discuției despre ștergere",
			helptip: "Face referire la subpagina de discuție din Wikipedia:Pagini de șters",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		}/*,

		// TwinkleConfig.xfdWatchList (string)
		// The watchlist setting of the XfD list page, *if* the discussion is on a separate page. Either "yes" (add to watchlist), "no" (don't
		// add to watchlist), or "default" (use setting from preferences). Default is "no" (Hehe. Seriously though, who wants to watch it?
		// Sorry in advance for any false positives.).
		{
			name: "xfdWatchList",
			label: "Add the daily log/list page to the watchlist (where applicable)",
			helptip: "This only applies for AfD and MfD, where the discussions are transcluded onto a daily log page (for AfD) or the main MfD page (for MfD).",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		},

		// TwinkleConfig.xfdWatchUser (string)
		// The watchlist setting of the user if he receives a notification. Either "yes" (add to watchlist), "no" (don't
		// add to watchlist), or "default" (use setting from preferences). Default is "default" (duh).
		{
			name: "xfdWatchUser",
			label: "Add the user talk page to watchlist (when notifying)",
			type: "enum",
			enumValues: Twinkle.config.commonEnums.watchlist
		}*/
	]
},

{
	title: "Ascuns",
	hidden: true,
	preferences: [
		// twinkle.header.js: portlet setup
		{
			name: "portletArea",
			type: "string"
		},
		{
			name: "portletId",
			type: "string"
		},
		{
			name: "portletName",
			type: "string"
		},
		{
			name: "portletType",
			type: "string"
		},
		{
			name: "portletNext",
			type: "string"
		},
		// twinklefluff.js: defines how many revision to query maximum, maximum possible is 50, default is 50
		{
			name: "revertMaxRevisions",
			type: "integer"
		},
		// twinklebatchdelete.js: How many pages should be processed at a time
		{
			name: "batchdeleteChunks",
			type: "integer"
		},
		// twinklebatchdelete.js: How many pages left in the process of being completed should allow a new batch to be initialized
		{
			name: "batchDeleteMinCutOff",
			type: "integer"
		},
		// twinklebatchdelete.js: How many pages should be processed maximum
		{
			name: "batchMax",
			type: "integer"
		},
		// twinklebatchprotect.js: How many pages should be processed at a time
		{
			name: "batchProtectChunks",
			type: "integer"
		},
		// twinklebatchprotect.js: How many pages left in the process of being completed should allow a new batch to be initialized
		{
			name: "batchProtectMinCutOff",
			type: "integer"
		},
		// twinklebatchundelete.js: How many pages should be processed at a time
		{
			name: "batchundeleteChunks",
			type: "integer"
		},
		// twinklebatchundelete.js: How many pages left in the process of being completed should allow a new batch to be initialized
		{
			name: "batchUndeleteMinCutOff",
			type: "integer"
		},
		// twinkledelimages.js: How many files should be processed at a time
		{
			name: "deliChunks",
			type: "integer"
		},
		// twinkledelimages.js: How many files should be processed maximum
		{
			name: "deliMax",
			type: "integer"
		}
	]
}

]; // end of Twinkle.config.sections

//{
//			name: "",
//			label: "",
//			type: ""
//		},


Twinkle.config.init = function twinkleconfigInit() {

	if ((mw.config.get("wgPageName") === "Wikipedia:Twinkle/Preferences" ||
	    (mw.config.get("wgNamespaceNumber") === 2 && mw.config.get("wgTitle").lastIndexOf("/Twinkle preferences") === (mw.config.get("wgTitle").length - 20))) &&
	    mw.config.get("wgAction") === "view") {
		// create the config page at Wikipedia:Twinkle/Preferences, and at user subpages (for testing purposes)

		if (!document.getElementById("twinkle-config")) {
			return;  // maybe the page is misconfigured, or something - but any attempt to modify it will be pointless
		}

		// set style (the url() CSS function doesn't seem to work from wikicode - ?!)
		document.getElementById("twinkle-config-titlebar").style.backgroundImage = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB%2FqqA%2BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhQTFRFr73ZobTPusjdsMHZp7nVwtDhzNbnwM3fu8jdq7vUt8nbxtDkw9DhpbfSvMrfssPZqLvVztbno7bRrr7W1d%2Fs1N7qydXk0NjpkW7Q%2BgAAADVJREFUeNoMwgESQCAAAMGLkEIi%2FP%2BnbnbpdB59app5Vdg0sXAoMZCpGoFbK6ciuy6FX4ABAEyoAef0BXOXAAAAAElFTkSuQmCC)";

		var contentdiv = document.getElementById("twinkle-config-content");
		contentdiv.textContent = "";  // clear children

		// let user know about possible conflict with monobook.js/vector.js file
		// (settings in that file will still work, but they will be overwritten by twinkleoptions.js settings)
		var contentnotice = document.createElement("p");
		// I hate innerHTML, but this is one thing it *is* good for...
		contentnotice.innerHTML = "<b>Before modifying your preferences here,</b> make sure you have removed any old <code>TwinkleConfig</code> and <code>FriendlyConfig</code> settings from your <a href=\"" + mw.util.getUrl("Special:MyPage/skin.js") + "\" title=\"Special:MyPage/skin.js\">user JavaScript file</a>.";
		contentdiv.appendChild(contentnotice);

		// look and see if the user does in fact have any old settings in their skin JS file
		var skinjs = new Morebits.wiki.page("User:" + mw.config.get("wgUserName") + "/" + mw.config.get("skin") + ".js");
		skinjs.setCallbackParameters(contentnotice);
		skinjs.load(Twinkle.config.legacyPrefsNotice);

		// start a table of contents
		var toctable = document.createElement("table");
		toctable.className = "toc";
		toctable.style.marginLeft = "0.4em";
		var toctr = document.createElement("tr");
		var toctd = document.createElement("td");
		// create TOC title
		var toctitle = document.createElement("div");
		toctitle.id = "toctitle";
		var toch2 = document.createElement("h2");
		toch2.textContent = "Contents ";
		toctitle.appendChild(toch2);
		// add TOC show/hide link
		var toctoggle = document.createElement("span");
		toctoggle.className = "toctoggle";
		toctoggle.appendChild(document.createTextNode("["));
		var toctogglelink = document.createElement("a");
		toctogglelink.className = "internal";
		toctogglelink.setAttribute("href", "#tw-tocshowhide");
		toctogglelink.textContent = "hide";
		toctoggle.appendChild(toctogglelink);
		toctoggle.appendChild(document.createTextNode("]"));
		toctitle.appendChild(toctoggle);
		toctd.appendChild(toctitle);
		// create item container: this is what we add stuff to
		var tocul = document.createElement("ul");
		toctogglelink.addEventListener("click", function twinkleconfigTocToggle() {
			var $tocul = $(tocul);
			$tocul.toggle();
			if ($tocul.find(":visible").length) {
				toctogglelink.textContent = "hide";
			} else {
				toctogglelink.textContent = "show";
			}
		}, false);
		toctd.appendChild(tocul);
		toctr.appendChild(toctd);
		toctable.appendChild(toctr);
		contentdiv.appendChild(toctable);

		var tocnumber = 1;

		var contentform = document.createElement("form");
		contentform.setAttribute("action", "javascript:void(0)");  // was #tw-save - changed to void(0) to work around Chrome issue
		contentform.addEventListener("submit", Twinkle.config.save, true);
		contentdiv.appendChild(contentform);

		var container = document.createElement("table");
		container.style.width = "100%";
		contentform.appendChild(container);

		$(Twinkle.config.sections).each(function(sectionkey, section) {
			if (section.hidden || (section.adminOnly && !Morebits.userIsInGroup("sysop"))) {
				return true;  // i.e. "continue" in this context
			}

			var configgetter;  // retrieve the live config values
			if (section.inFriendlyConfig) {
				configgetter = Twinkle.getFriendlyPref;
			} else {
				configgetter = Twinkle.getPref;
			}

			// add to TOC
			var tocli = document.createElement("li");
			tocli.className = "toclevel-1";
			var toca = document.createElement("a");
			toca.setAttribute("href", "#twinkle-config-section-" + tocnumber.toString());
			toca.appendChild(document.createTextNode(section.title));
			tocli.appendChild(toca);
			tocul.appendChild(tocli);

			var row = document.createElement("tr");
			var cell = document.createElement("td");
			cell.setAttribute("colspan", "3");
			var heading = document.createElement("h4");
			heading.style.borderBottom = "1px solid gray";
			heading.style.marginTop = "0.2em";
			heading.id = "twinkle-config-section-" + (tocnumber++).toString();
			heading.appendChild(document.createTextNode(section.title));
			cell.appendChild(heading);
			row.appendChild(cell);
			container.appendChild(row);

			var rowcount = 1;  // for row banding

			// add each of the preferences to the form
			$(section.preferences).each(function(prefkey, pref) {
				if (pref.adminOnly && !Morebits.userIsInGroup("sysop")) {
					return true;  // i.e. "continue" in this context
				}

				row = document.createElement("tr");
				row.style.marginBottom = "0.2em";
				// create odd row banding
				if (rowcount++ % 2 === 0) {
					row.style.backgroundColor = "rgba(128, 128, 128, 0.1)";
				}
				cell = document.createElement("td");

				var label, input;
				switch (pref.type) {

					case "boolean":  // create a checkbox
						cell.setAttribute("colspan", "2");

						label = document.createElement("label");
						input = document.createElement("input");
						input.setAttribute("type", "checkbox");
						input.setAttribute("id", pref.name);
						input.setAttribute("name", pref.name);
						if (configgetter(pref.name) === true) {
							input.setAttribute("checked", "checked");
						}
						label.appendChild(input);
						label.appendChild(document.createTextNode(" " + pref.label));
						cell.appendChild(label);
						break;

					case "string":  // create an input box
					case "integer":
						// add label to first column
						cell.style.textAlign = "right";
						cell.style.paddingRight = "0.5em";
						label = document.createElement("label");
						label.setAttribute("for", pref.name);
						label.appendChild(document.createTextNode(pref.label + ":"));
						cell.appendChild(label);
						row.appendChild(cell);

						// add input box to second column
						cell = document.createElement("td");
						cell.style.paddingRight = "1em";
						input = document.createElement("input");
						input.setAttribute("type", "text");
						input.setAttribute("id", pref.name);
						input.setAttribute("name", pref.name);
						if (pref.type === "integer") {
							input.setAttribute("size", 6);
							input.setAttribute("type", "number");
							input.setAttribute("step", "1");  // integers only
						}
						if (configgetter(pref.name)) {
							input.setAttribute("value", configgetter(pref.name));
						}
						cell.appendChild(input);
						break;

					case "enum":  // create a combo box
						// add label to first column
						// note: duplicates the code above, under string/integer
						cell.style.textAlign = "right";
						cell.style.paddingRight = "0.5em";
						label = document.createElement("label");
						label.setAttribute("for", pref.name);
						label.appendChild(document.createTextNode(pref.label + ":"));
						cell.appendChild(label);
						row.appendChild(cell);

						// add input box to second column
						cell = document.createElement("td");
						cell.style.paddingRight = "1em";
						input = document.createElement("select");
						input.setAttribute("id", pref.name);
						input.setAttribute("name", pref.name);
						$.each(pref.enumValues, function(enumvalue, enumdisplay) {
							var option = document.createElement("option");
							option.setAttribute("value", enumvalue);
							if (configgetter(pref.name) == enumvalue) {
								option.setAttribute("selected", "selected");
							}
							option.appendChild(document.createTextNode(enumdisplay));
							input.appendChild(option);
						});
						cell.appendChild(input);
						break;

					case "set":  // create a set of check boxes
						// add label first of all
						cell.setAttribute("colspan", "2");
						label = document.createElement("label");  // not really necessary to use a label element here, but we do it for consistency of styling
						label.appendChild(document.createTextNode(pref.label + ":"));
						cell.appendChild(label);

						var checkdiv = document.createElement("div");
						checkdiv.style.paddingLeft = "1em";
						var worker = function(itemkey, itemvalue) {
							var checklabel = document.createElement("label");
							checklabel.style.marginRight = "0.7em";
							checklabel.style.display = "inline-block";
							var check = document.createElement("input");
							check.setAttribute("type", "checkbox");
							check.setAttribute("id", pref.name + "_" + itemkey);
							check.setAttribute("name", pref.name + "_" + itemkey);
							if (configgetter(pref.name) && configgetter(pref.name).indexOf(itemkey) !== -1) {
								check.setAttribute("checked", "checked");
							}
							// cater for legacy integer array values for unlinkNamespaces (this can be removed a few years down the track...)
							if (pref.name === "unlinkNamespaces") {
								if (configgetter(pref.name) && configgetter(pref.name).indexOf(parseInt(itemkey, 10)) !== -1) {
									check.setAttribute("checked", "checked");
								}
							}
							checklabel.appendChild(check);
							checklabel.appendChild(document.createTextNode(itemvalue));
							checkdiv.appendChild(checklabel);
						};
						if (pref.setDisplayOrder) {
							// add check boxes according to the given display order
							$.each(pref.setDisplayOrder, function(itemkey, item) {
								worker(item, pref.setValues[item]);
							});
						} else {
							// add check boxes according to the order it gets fed to us (probably strict alphabetical)
							$.each(pref.setValues, worker);
						}
						cell.appendChild(checkdiv);
						break;

					case "customList":
						// add label to first column
						cell.style.textAlign = "right";
						cell.style.paddingRight = "0.5em";
						label = document.createElement("label");
						label.setAttribute("for", pref.name);
						label.appendChild(document.createTextNode(pref.label + ":"));
						cell.appendChild(label);
						row.appendChild(cell);

						// add button to second column
						cell = document.createElement("td");
						cell.style.paddingRight = "1em";
						var button = document.createElement("button");
						button.setAttribute("id", pref.name);
						button.setAttribute("name", pref.name);
						button.setAttribute("type", "button");
						button.addEventListener("click", Twinkle.config.listDialog.display, false);
						// use jQuery data on the button to store the current config value
						$(button).data({
							value: configgetter(pref.name),
							pref: pref,
							inFriendlyConfig: section.inFriendlyConfig
						});
						button.appendChild(document.createTextNode("Edit items"));
						cell.appendChild(button);
						break;

					default:
						alert("twinkleconfig: unknown data type for preference " + pref.name);
						break;
				}
				row.appendChild(cell);

				// add help tip
				cell = document.createElement("td");
				cell.style.fontSize = "90%";

				cell.style.color = "gray";
				if (pref.helptip) {
					cell.innerHTML = pref.helptip;
				}
				// add reset link (custom lists don't need this, as their config value isn't displayed on the form)
				if (pref.type !== "customList") {
					var resetlink = document.createElement("a");
					resetlink.setAttribute("href", "#tw-reset");
					resetlink.setAttribute("id", "twinkle-config-reset-" + pref.name);
					resetlink.addEventListener("click", Twinkle.config.resetPrefLink, false);
					if (resetlink.style.styleFloat) {  // IE (inc. IE9)
						resetlink.style.styleFloat = "right";
					} else {  // standards
						resetlink.style.cssFloat = "right";
					}
					resetlink.style.margin = "0 0.6em";
					resetlink.appendChild(document.createTextNode("Reset"));
					cell.appendChild(resetlink);
				}
				row.appendChild(cell);

				container.appendChild(row);
				return true;
			});
			return true;
		});

		var footerbox = document.createElement("div");
		footerbox.setAttribute("id", "twinkle-config-buttonpane");
		footerbox.style.backgroundColor = "#BCCADF";
		footerbox.style.padding = "0.5em";
		var button = document.createElement("button");
		button.setAttribute("id", "twinkle-config-submit");
		button.setAttribute("type", "submit");
		button.appendChild(document.createTextNode("Save changes"));
		footerbox.appendChild(button);
		var footerspan = document.createElement("span");
		footerspan.className = "plainlinks";
		footerspan.style.marginLeft = "2.4em";
		footerspan.style.fontSize = "90%";
		var footera = document.createElement("a");
		footera.setAttribute("href", "#tw-reset-all");
		footera.setAttribute("id", "twinkle-config-resetall");
		footera.addEventListener("click", Twinkle.config.resetAllPrefs, false);
		footera.appendChild(document.createTextNode("Restaurează valorile implicite"));
		footerspan.appendChild(footera);
		footerbox.appendChild(footerspan);
		contentform.appendChild(footerbox);

		// since all the section headers exist now, we can try going to the requested anchor
		if (location.hash) {
			location.hash = location.hash;
		}

	} else if (mw.config.get("wgNamespaceNumber") === 2) {

		var box = document.createElement("div");
		box.setAttribute("id", "twinkle-config-headerbox");
		box.style.border = "1px #f60 solid";
		box.style.background = "#fed";
		box.style.padding = "0.6em";
		box.style.margin = "0.5em auto";
		box.style.textAlign = "center";

		var link;
		if (mw.config.get("wgTitle") === mw.config.get("wgUserName") + "/twinkleoptions.js") {
			// place "why not try the preference panel" notice
			box.style.fontWeight = "bold";
			box.style.width = "80%";
			box.style.borderWidth = "2px";

			if (mw.config.get("wgArticleId") > 0) {  // page exists
				box.appendChild(document.createTextNode("Această pagină conține preferințele dumneavoastră privind funcționarea lui Twinkle. O puteți modifica folosind "));
			} else {  // page does not exist
				box.appendChild(document.createTextNode("Îl puteți configura pe Twinkle pentru a funcționa cum doriți folosind "));
			}
			link = document.createElement("a");
			link.setAttribute("href", mw.util.getUrl("Wikipedia:Twinkle/Preferences") );
			link.appendChild(document.createTextNode("panoul de preferințe Twinkle"));
			box.appendChild(link);
			box.appendChild(document.createTextNode(", sau modificând această pagină."));
			$(box).insertAfter($("#contentSub"));

		} else if (mw.config.get("wgTitle").indexOf(mw.config.get("wgUserName")) === 0 && mw.config.get("wgTitle").lastIndexOf(".js") == mw.config.get("wgTitle").length - 3) {
			// place "Looking for Twinkle options?" notice
			box.style.width = "60%";

			box.appendChild(document.createTextNode("Dacă doriți să setați preferințele Twinkle, puteți folosi "));
			link = document.createElement("a");
			link.setAttribute("href", mw.util.getUrl("Wikipedia:Twinkle/Preferences") );
			link.appendChild(document.createTextNode("panoul de preferințe Twinkle"));
			box.appendChild(link);
			box.appendChild(document.createTextNode("."));
			$(box).insertAfter($("#contentSub"));
		}
	}
};

// Morebits.wiki.page callback from init code
Twinkle.config.legacyPrefsNotice = function twinkleconfigLegacyPrefsNotice(pageobj) {
	var text = pageobj.getPageText();
	var contentnotice = pageobj.getCallbackParameters();
	if (text.indexOf("TwinkleConfig") !== -1 || text.indexOf("FriendlyConfig") !== -1) {
		contentnotice.innerHTML = '<table class="plainlinks ombox ombox-content"><tr><td class="mbox-image">' +
			'<img alt="" src="//upload.wikimedia.org/wikipedia/en/3/38/Imbox_content.png" /></td>' +
			'<td class="mbox-text"><p><big><b>Înainte de a modifica setările aici,</b> trebuie să eliminați vechile setări pentru Twinkle și Friendly din skinul JavaScript personal.</big></p>' +
			'<p>Pentru aceasta, puteți <a href="' + mw.config.get("wgScript") + '?title=User:' + encodeURIComponent(mw.config.get("wgUserName")) + '/' + mw.config.get("skin") + '.js&action=edit" target="_tab"><b>modifica JavaScriptul personal</b></a>, eliminând toate liniile ce fac referire la <code>TwinkleConfig</code> și <code>FriendlyConfig</code>.</p>' +
			'</td></tr></table>';
	} else {
		$(contentnotice).remove();
	}
};

// custom list-related stuff

Twinkle.config.listDialog = {};

Twinkle.config.listDialog.addRow = function twinkleconfigListDialogAddRow(dlgtable, value, label) {
	var contenttr = document.createElement("tr");
	// "remove" button
	var contenttd = document.createElement("td");
	var removeButton = document.createElement("button");
	removeButton.setAttribute("type", "button");
	removeButton.addEventListener("click", function() { $(contenttr).remove(); }, false);
	removeButton.textContent = "Remove";
	contenttd.appendChild(removeButton);
	contenttr.appendChild(contenttd);

	// value input box
	contenttd = document.createElement("td");
	var input = document.createElement("input");
	input.setAttribute("type", "text");
	input.className = "twinkle-config-customlist-value";
	input.style.width = "97%";
	if (value) {
		input.setAttribute("value", value);
	}
	contenttd.appendChild(input);
	contenttr.appendChild(contenttd);

	// label input box
	contenttd = document.createElement("td");
	input = document.createElement("input");
	input.setAttribute("type", "text");
	input.className = "twinkle-config-customlist-label";
	input.style.width = "98%";
	if (label) {
		input.setAttribute("value", label);
	}
	contenttd.appendChild(input);
	contenttr.appendChild(contenttd);

	dlgtable.appendChild(contenttr);
};

Twinkle.config.listDialog.display = function twinkleconfigListDialogDisplay(e) {
	var $prefbutton = $(e.target);
	var curvalue = $prefbutton.data("value");
	var curpref = $prefbutton.data("pref");

	var dialog = new Morebits.simpleWindow(720, 400);
	dialog.setTitle(curpref.label);
	dialog.setScriptName("Twinkle preferences");

	var dialogcontent = document.createElement("div");
	var dlgtable = document.createElement("table");
	dlgtable.className = "wikitable";
	dlgtable.style.margin = "1.4em 1em";
	dlgtable.style.width = "auto";

	var dlgtbody = document.createElement("tbody");

	// header row
	var dlgtr = document.createElement("tr");
	// top-left cell
	var dlgth = document.createElement("th");
	dlgth.style.width = "5%";
	dlgtr.appendChild(dlgth);
	// value column header
	dlgth = document.createElement("th");
	dlgth.style.width = "35%";
	dlgth.textContent = (curpref.customListValueTitle ? curpref.customListValueTitle : "Value");
	dlgtr.appendChild(dlgth);
	// label column header
	dlgth = document.createElement("th");
	dlgth.style.width = "60%";
	dlgth.textContent = (curpref.customListLabelTitle ? curpref.customListLabelTitle : "Label");
	dlgtr.appendChild(dlgth);
	dlgtbody.appendChild(dlgtr);

	// content rows
	var gotRow = false;
	$.each(curvalue, function(k, v) {
		gotRow = true;
		Twinkle.config.listDialog.addRow(dlgtbody, v.value, v.label);
	});
	// if there are no values present, add a blank row to start the user off
	if (!gotRow) {
		Twinkle.config.listDialog.addRow(dlgtbody);
	}

	// final "add" button
	var dlgtfoot = document.createElement("tfoot");
	dlgtr = document.createElement("tr");
	var dlgtd = document.createElement("td");
	dlgtd.setAttribute("colspan", "3");
	var addButton = document.createElement("button");
	addButton.style.minWidth = "8em";
	addButton.setAttribute("type", "button");
	addButton.addEventListener("click", function(e) {
		Twinkle.config.listDialog.addRow(dlgtbody);
	}, false);
	addButton.textContent = "Add";
	dlgtd.appendChild(addButton);
	dlgtr.appendChild(dlgtd);
	dlgtfoot.appendChild(dlgtr);

	dlgtable.appendChild(dlgtbody);
	dlgtable.appendChild(dlgtfoot);
	dialogcontent.appendChild(dlgtable);

	// buttonpane buttons: [Save changes] [Reset] [Cancel]
	var button = document.createElement("button");
	button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
	button.addEventListener("click", function(e) {
		Twinkle.config.listDialog.save($prefbutton, dlgtbody);
		dialog.close();
	}, false);
	button.textContent = "Save changes";
	dialogcontent.appendChild(button);
	button = document.createElement("button");
	button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
	button.addEventListener("click", function(e) {
		Twinkle.config.listDialog.reset($prefbutton, dlgtbody);
	}, false);
	button.textContent = "Reset";
	dialogcontent.appendChild(button);
	button = document.createElement("button");
	button.setAttribute("type", "submit");  // so Morebits.simpleWindow puts the button in the button pane
	button.addEventListener("click", function(e) {
		dialog.close();  // the event parameter on this function seems to be broken
	}, false);
	button.textContent = "Cancel";
	dialogcontent.appendChild(button);

	dialog.setContent(dialogcontent);
	dialog.display();
};

// Resets the data value, re-populates based on the new (default) value, then saves the
// old data value again (less surprising behaviour)
Twinkle.config.listDialog.reset = function twinkleconfigListDialogReset(button, tbody) {
	// reset value on button
	var $button = $(button);
	var curpref = $button.data("pref");
	var oldvalue = $button.data("value");
	Twinkle.config.resetPref(curpref, $button.data("inFriendlyConfig"));

	// reset form
	var $tbody = $(tbody);
	$tbody.find("tr").slice(1).remove();  // all rows except the first (header) row
	// add the new values
	var curvalue = $button.data("value");
	$.each(curvalue, function(k, v) {
		Twinkle.config.listDialog.addRow(tbody, v.value, v.label);
	});

	// save the old value
	$button.data("value", oldvalue);
};

Twinkle.config.listDialog.save = function twinkleconfigListDialogSave(button, tbody) {
	var result = [];
	var current = {};
	$(tbody).find('input[type="text"]').each(function(inputkey, input) {
		if ($(input).hasClass("twinkle-config-customlist-value")) {
			current = { value: input.value };
		} else {
			current.label = input.value;
			// exclude totally empty rows
			if (current.value || current.label) {
				result.push(current);
			}
		}
	});
	$(button).data("value", result);
};

// reset/restore defaults

Twinkle.config.resetPrefLink = function twinkleconfigResetPrefLink(e) {
	var wantedpref = e.target.id.substring(21); // "twinkle-config-reset-" prefix is stripped

	// search tactics
	$(Twinkle.config.sections).each(function(sectionkey, section) {
		if (section.hidden || (section.adminOnly && !Morebits.userIsInGroup("sysop"))) {
			return true;  // continue: skip impossibilities
		}

		var foundit = false;

		$(section.preferences).each(function(prefkey, pref) {
			if (pref.name !== wantedpref) {
				return true;  // continue
			}
			Twinkle.config.resetPref(pref, section.inFriendlyConfig);
			foundit = true;
			return false;  // break
		});

		if (foundit) {
			return false;  // break
		}
	});
	return false;  // stop link from scrolling page
};

Twinkle.config.resetPref = function twinkleconfigResetPref(pref, inFriendlyConfig) {
	switch (pref.type) {

		case "boolean":
			document.getElementById(pref.name).checked = (inFriendlyConfig ?
				Twinkle.defaultConfig.friendly[pref.name] : Twinkle.defaultConfig.twinkle[pref.name]);
			break;

		case "string":
		case "integer":
		case "enum":
			document.getElementById(pref.name).value = (inFriendlyConfig ?
				Twinkle.defaultConfig.friendly[pref.name] : Twinkle.defaultConfig.twinkle[pref.name]);
			break;

		case "set":
			$.each(pref.setValues, function(itemkey, itemvalue) {
				if (document.getElementById(pref.name + "_" + itemkey)) {
					document.getElementById(pref.name + "_" + itemkey).checked = ((inFriendlyConfig ?
						Twinkle.defaultConfig.friendly[pref.name] : Twinkle.defaultConfig.twinkle[pref.name]).indexOf(itemkey) !== -1);
				}
			});
			break;

		case "customList":
			$(document.getElementById(pref.name)).data("value", (inFriendlyConfig ?
				Twinkle.defaultConfig.friendly[pref.name] : Twinkle.defaultConfig.twinkle[pref.name]));
			break;

		default:
			alert("twinkleconfig: unknown data type for preference " + pref.name);
			break;
	}
};

Twinkle.config.resetAllPrefs = function twinkleconfigResetAllPrefs() {
	// no confirmation message - the user can just refresh/close the page to abort
	$(Twinkle.config.sections).each(function(sectionkey, section) {
		if (section.hidden || (section.adminOnly && !Morebits.userIsInGroup("sysop"))) {
			return true;  // continue: skip impossibilities
		}
		$(section.preferences).each(function(prefkey, pref) {
			if (!pref.adminOnly || Morebits.userIsInGroup("sysop")) {
				Twinkle.config.resetPref(pref, section.inFriendlyConfig);
			}
		});
		return true;
	});
	return false;  // stop link from scrolling page
};

Twinkle.config.save = function twinkleconfigSave(e) {
	Morebits.status.init( document.getElementById("twinkle-config-content") );

	Morebits.wiki.actionCompleted.notice = "Salvează";

	var userjs = "User:" + mw.config.get("wgUserName") + "/twinkleoptions.js";
	var wikipedia_page = new Morebits.wiki.page(userjs, "Saving preferences to " + userjs);
	wikipedia_page.setCallbackParameters(e.target);
	wikipedia_page.load(Twinkle.config.writePrefs);

	return false;
};


(function() {
	var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		gap,
		indent = '  ',  // hardcoded indent
		meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' };

	function quote(string) {
		escapable.lastIndex = 0;
		return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
			var c = meta[a];
			return typeof c === 'string' ? c :	'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
		}) + '"' : '"' + string + '"';
	}

	function str(key, holder) {
		var i, k, v, length, mind = gap, partial, value = holder[key];

		if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
			value = value.toJSON(key);
		}

		switch (typeof value) {
		case 'string':
			return quote(value);
		case 'number':
			return isFinite(value) ? String(value) : 'null';
		case 'boolean':
		case 'null':
			return String(value);
		case 'object':
			if (!value) {
				return 'null';
			}
			gap += indent;
			partial = [];
			if (Object.prototype.toString.apply(value) === '[object Array]') {
				length = value.length;
				for (i = 0; i < length; i += 1) {
					partial[i] = str(i, value) || 'null';
				}
				v = partial.length === 0 ? '[]' : gap ?
					'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
					'[' + partial.join(',') + ']';
				gap = mind;
				return v;
			}
			for (k in value) {
				if (Object.prototype.hasOwnProperty.call(value, k)) {
					v = str(k, value);
					if (v) {
						partial.push(quote(k) + (gap ? ': ' : ':') + v);
					}
				}
			}
			v = partial.length === 0 ? '{}' : gap ?
				'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
				'{' + partial.join(',') + '}';
			gap = mind;
			return v;
		default:
			throw new Error( "JSON.stringify: unknown data type" );
		}
	}

}());

Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
	var form = pageobj.getCallbackParameters();
	var statelem = pageobj.getStatusElement();

	// this is the object which gets serialized into JSON
	var newConfig = {
		twinkle: {},
		friendly: {}
	};

	// keeping track of all preferences that we encounter
	// any others that are set in the user's current config are kept
	// this way, preferences that this script doesn't know about are not lost
	// (it does mean obsolete prefs will never go away, but... ah well...)
	var foundTwinklePrefs = [], foundFriendlyPrefs = [];

	// a comparison function is needed later on
	// it is just enough for our purposes (i.e. comparing strings, numbers, booleans,
	// arrays of strings, and arrays of { value, label })
	// and it is not very robust: e.g. compare([2], ["2"]) === true, and
	// compare({}, {}) === false, but it's good enough for our purposes here
	var compare = function(a, b) {
		if (Object.prototype.toString.apply(a) === "[object Array]") {
			if (a.length !== b.length) {
				return false;
			}
			var asort = a.sort(), bsort = b.sort();
			for (var i = 0; asort[i]; i++) {
				// comparison of the two properties of custom lists
				if ((typeof asort[i] === "object") && (asort[i].label !== bsort[i].label ||
					asort[i].value !== bsort[i].value)) {
					return false;
				} else if (asort[i].toString() !== bsort[i].toString()) { 
					return false;
				}
			}
			return true;
		} else {
			return a === b;
		}
	};

	$(Twinkle.config.sections).each(function(sectionkey, section) {
		if (section.adminOnly && !Morebits.userIsInGroup("sysop")) {
			return;  // i.e. "continue" in this context
		}

		// reach each of the preferences from the form
		$(section.preferences).each(function(prefkey, pref) {
			var userValue;  // = undefined

			// only read form values for those prefs that have them
			if (!section.hidden && (!pref.adminOnly || Morebits.userIsInGroup("sysop"))) {
				switch (pref.type) {

					case "boolean":  // read from the checkbox
						userValue = form[pref.name].checked;
						break;

					case "string":  // read from the input box or combo box
					case "enum":
						userValue = form[pref.name].value;
						break;

					case "integer":  // read from the input box
						userValue = parseInt(form[pref.name].value, 10);
						if (isNaN(userValue)) {
							Morebits.status.warn("Saving", "The value you specified for " + pref.name + " (" + pref.value + ") was invalid.  The save will continue, but the invalid data value will be skipped.");
							userValue = null;
						}
						break;

					case "set":  // read from the set of check boxes
						userValue = [];
						if (pref.setDisplayOrder) {
							// read only those keys specified in the display order
							$.each(pref.setDisplayOrder, function(itemkey, item) {
								if (form[pref.name + "_" + item].checked) {
									userValue.push(item);
								}
							});
						} else {
							// read all the keys in the list of values
							$.each(pref.setValues, function(itemkey, itemvalue) {
								if (form[pref.name + "_" + itemkey].checked) {
									userValue.push(itemkey);
								}
							});
						}
						break;

					case "customList":  // read from the jQuery data stored on the button object
						userValue = $(form[pref.name]).data("value");
						break;

					default:
						alert("twinkleconfig: unknown data type for preference " + pref.name);
						break;
				}
			}

			// only save those preferences that are *different* from the default
			if (section.inFriendlyConfig) {
				if (typeof userValue !== "undefined" && !compare(userValue, Twinkle.defaultConfig.friendly[pref.name])) {
					newConfig.friendly[pref.name] = userValue;
				}
				foundFriendlyPrefs.push(pref.name);
			} else {
				if (typeof userValue !== "undefined" && !compare(userValue, Twinkle.defaultConfig.twinkle[pref.name])) {
					newConfig.twinkle[pref.name] = userValue;
				}
				foundTwinklePrefs.push(pref.name);
			}
		});
	});

	if (Twinkle.prefs) {
		$.each(Twinkle.prefs.twinkle, function(tkey, tvalue) {
			if (foundTwinklePrefs.indexOf(tkey) === -1) {
				newConfig.twinkle[tkey] = tvalue;
			}
		});
		$.each(Twinkle.prefs.friendly, function(fkey, fvalue) {
			if (foundFriendlyPrefs.indexOf(fkey) === -1) {
				newConfig.friendly[fkey] = fvalue;
			}
		});
	}

	var text =
		"// twinkleoptions.js: fișier de preferințe personale pentru Twinkle\n" +
		"//\n" +
		"// NOTĂ: Cea mai simplă cale de a configura Twinkle este din\n" +
		"// panoul de preferințe Twinkle, de la [[" + mw.config.get("wgPageName") + "]].\n" +
		"//\n" +
		"// Acest fișier este GENERAT AUTOMAT. Orice modificări efectuați aici (afară de\n" +
		"// modificarea parametrilor de configurare cu respectarea sintaxei JavaScript)\n" +
		"// vor fi suprascrise la următorul click pe opțiunea \"salvează\" din panoul de\n" +
		"// preferințe Twinkle. Dacă modificați acest fișier, atenție la sintaxa JavaScript.\n" +
		"\n" +
		"window.Twinkle.prefs = ";
	text += JSON.stringify(newConfig, null, 2);
	text +=
		";\n" +
		"\n" +
		"// Sfârșit twinkleoptions.js\n";

	pageobj.setPageText(text);
	pageobj.setEditSummary("Salvare preferințe Twinkle: modificare automată din pagina [[" + mw.config.get("wgPageName") + "]] ([[WP:TW|TW]])");
	pageobj.setCreateOption("recreate");
	pageobj.save(Twinkle.config.saveSuccess);
};

Twinkle.config.saveSuccess = function twinkleconfigSaveSuccess(pageobj) {
	pageobj.getStatusElement().info("successful");

	var noticebox = document.createElement("div");
	noticebox.className = "successbox";
	noticebox.style.fontSize = "100%";
	noticebox.style.marginTop = "2em";
	noticebox.innerHTML = "<p><b>Preferințele Twinkle au fost salvate.</b></p><p>Pentru a vedea schimbările, va trebui să <a href=\"" + mw.util.getUrl(":en:WP:BYPASS") + "\" title=\"WP:BYPASS\"><b>reîmprospătați cache-ul browserului</b></a>.</p>";
	Morebits.status.root.appendChild(noticebox);
	var noticeclear = document.createElement("br");
	noticeclear.style.clear = "both";
	Morebits.status.root.appendChild(noticeclear);
};

/*
****************************************
*** twinkledelimages.js: Batch deletion of images (sysops only)
****************************************
* Mode of invocation:     Tab ("Deli-batch")
* Active on:              Existing non-special pages
* Config directives in:   TwinkleConfig
*/

Twinkle.delimages = function twinkledeli() {
	if( mw.config.get( 'wgNamespaceNumber' ) < 0 || !mw.config.get( 'wgCurRevisionId' ) ) {
		return;
	}
	if( Morebits.userIsInGroup( 'sysop' ) ) {
		twAddPortletLink(Twinkle.delimages.callback, "Deli-batch", "tw-deli", "șterge fișierele de pe această pagină");
	}
};

Twinkle.delimages.unlinkCache = {};
Twinkle.delimages.callback = function twinkledeliCallback() {
	var Window = new Morebits.simpleWindow( 800, 400 );
	Window.setTitle( "Batch file deletion" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#delimages" );

	var form = new Morebits.quickForm( Twinkle.delimages.callback.evaluate );
	form.append( {
		type: 'checkbox',
		list: [
			{
				label: 'Delete files',
				name: 'delete_image',
				value: 'delete',
				checked: true
			},
			{
				label: 'Unlink uses of this file',
				name: 'unlink_image',
				value: 'unlink',
				checked: true
			}
		]
	} );
	form.append( {
		type: 'textarea',
		name: 'reason',
		label: 'Reason: '
	} );
	var query;
	if( mw.config.get( 'wgNamespaceNumber' ) === mw.config.get("wgNamespaceIds").CATEGORY ) {
		query = {
			'action': 'query',
			'generator': 'categorymembers',
			'gcmtitle': mw.config.get( 'wgPageName' ),
			'gcmnamespace': mw.config.get("wgNamespaceIds").IMAGE,
			'gcmlimit' : Twinkle.getPref('deliMax'), 
			'prop': [ 'imageinfo', 'categories', 'revisions' ],
			'grvlimit': 1,
			'grvprop': [ 'user' ]
		};
	} else {
		query = {
			'action': 'query',
			'generator': 'images',
			'titles': mw.config.get( 'wgPageName' ),
			'prop': [ 'imageinfo', 'categories', 'revisions' ],
			'gimlimit': 'max'
		};
	}
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing files', query, function( self ) {
		var xmlDoc = self.responseXML;
		var images = $(xmlDoc).find('page[imagerepository="local"]');
		var list = [];

		$.each(images, function() {
			var $self = $(this);
			var image = $self.attr('title');
			var user = $self.find('imageinfo ii').attr('user');
			var last_edit = $self.find('revisions rev').attr('user');
			var disputed = $self.find('categories cl[title="Category:Contested candidates for speedy deletion"]').length > 0;
			list.push( {
				'label': image + ' - author: ' + user + ', last edit from: ' + last_edit + ( disputed ? ' DISPUTED' : '' ),
				'value': image,
				'checked': !disputed
			});
		});

		self.params.form.append( {
			type: 'checkbox',
			name: 'images',
			list: list
		}
	);
	self.params.form.append( { type:'submit' } );

	var result = self.params.form.render();
	self.params.Window.setContent( result );


}  );

wikipedia_api.params = { form:form, Window:Window };
wikipedia_api.post();
var root = document.createElement( 'div' );
Morebits.status.init( root );
Window.setContent( root );
Window.display();
};

Twinkle.delimages.currentDeleteCounter = 0;
Twinkle.delimages.currentUnlinkCounter = 0;
Twinkle.delimages.currentdeletor = 0;
Twinkle.delimages.callback.evaluate = function twinkledeliCallbackEvaluate(event) {
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!
	var images = event.target.getChecked( 'images' );
	var reason = event.target.reason.value;
	var delete_image = event.target.delete_image.checked;
	var unlink_image = event.target.unlink_image.checked;
	if( ! reason ) {
		return;
	}

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( event.target );

	function toCall( work ) {
		if( work.length === 0 && Twinkle.delimages.currentDeleteCounter <= 0 && Twinkle.delimages.currentUnlinkCounter <= 0 ) {
			window.clearInterval( Twinkle.delimages.currentdeletor );
			Morebits.wiki.removeCheckpoint();
			return;
		} else if( work.length !== 0 && Twinkle.delimages.currentDeleteCounter <= Twinkle.getPref('batchDeleteMinCutOff') && Twinkle.delimages.currentUnlinkCounter <= Twinkle.getPref('batchDeleteMinCutOff') ) {
			Twinkle.delimages.unlinkCache = []; // Clear the cache
			var images = work.shift();
			Twinkle.delimages.currentDeleteCounter = images.length;
			Twinkle.delimages.currentUnlinkCounter = images.length;
			var i;
			for( i = 0; i < images.length; ++i ) {
				var image = images[i];
				var query = {
					'action': 'query',
					'titles': image
				};
				var wikipedia_api = new Morebits.wiki.api( 'Checking if file ' + image + ' exists', query, Twinkle.delimages.callbacks.main );
				wikipedia_api.params = { image:image, reason:reason, unlink_image:unlink_image, delete_image:delete_image };
				wikipedia_api.post();
			}
		}
	}
	var work = images.chunk( Twinkle.getPref('deliChunks') );
	Morebits.wiki.addCheckpoint();
	Twinkle.delimages.currentdeletor = window.setInterval( toCall, 1000, work );
};
Twinkle.delimages.callbacks = {
	main: function( self ) {
		var xmlDoc = self.responseXML;
		var $data = $(xmlDoc);

		var normal = $data.find('normalized n').attr('to');

		if( normal ) {
			self.params.image = normal;
		}

		var exists = $data.find('pages page[title="'+self.params.image.replace( /"/g, '\\"')+'"]:not([missing])').length > 0;

		if( ! exists ) {
			self.statelem.error( "It seems that the page doesn't exists, perhaps it has already been deleted" );
			return;
		}
		if( self.params.unlink_image ) {
			var query = {
				'action': 'query',
				'list': 'imageusage',
				'iutitle': self.params.image,
				'iulimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500 // 500 is max for normal users, 5000 for bots and sysops
			};
			var wikipedia_api = new Morebits.wiki.api( 'Grabbing file links', query, Twinkle.delimages.callbacks.unlinkImageInstancesMain );
			wikipedia_api.params = self.params;
			wikipedia_api.post();
		}
		if( self.params.delete_image ) {

			var imagepage = new Morebits.wiki.page( self.params.image, 'șterg fișierul');
			imagepage.setEditSummary( "șters pentru că: \"" + self.params.reason + "\"." + Twinkle.getPref('deletionSummaryAd'));
			imagepage.deletePage();
		}
	},
	unlinkImageInstancesMain: function( self ) {
		var xmlDoc = self.responseXML;
		var instances = [];
		$(xmlDoc).find('imageusage iu').each(function(){
			instances.push($(this).attr('title'));
		});
		if( instances.length === 0 ) {
			--twinklebatchdelete.currentUnlinkCounter;
			return;
		}

		$.each( instances, function(k,title) {
			page = new Morebits.wiki.page(title, "Unlinking instances on " + title);
			page.setFollowRedirect(true);
			page.setCallbackParameters({'image': self.params.image, 'reason': self.params.reason});
			page.load(Twinkle.delimages.callbacks.unlinkImageInstances);

		});
	},
	unlinkImageInstances: function( self ) {
		var params = self.getCallbackParameters();
		var statelem = self.getStatusElement();

		var image = params.image.replace( /^(?:Image|File):/, '' );
		var old_text = self.getPageText();
		var wikiPage = new Mediawiki.Page( old_text );
		wikiPage.commentOutImage( image , 'Commented out because image was deleted' );
		var text = wikiPage.getText();

		if( text === old_text ) {
			statelem.error( 'failed to unlink image ' + image +' from ' + self.getPageName() );
			return;
		}
		self.setPageText(text);
		self.setEditSummary('Removing instance of file ' + image + " that has been deleted because \"" + params.reason + "\")" + "; " + Twinkle.getPref('deletionSummaryAd'));
		self.setCreateOption('nocreate');
		self.save();
	}
};


/*
 ****************************************
 *** twinklediff.js: Diff module
 ****************************************
 * Mode of invocation:     Tab on non-diff pages ("Last"); tabs on diff pages ("Since", "Since mine", "Current")
 * Active on:              Existing non-special pages
 * Config directives in:   TwinkleConfig
 */

Twinkle.diff = function twinklediff() { 
	if( mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId') ) {
		return;
	}

	var query = {
		'title': mw.config.get('wgPageName'),
		'diff': 'cur',
		'oldid': 'prev'
	};

	twAddPortletLink( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), 'Ultima', 'tw-lastdiff', 'Show most recent diff' );

	// Show additional tabs only on diff pages
	if (Morebits.queryString.exists('diff')) {
		twAddPortletLink(function(){Twinkle.diff.evaluate(false);}, 'De la', 'tw-since', 'Arată diferența între ultimul diff și versiunea utilizatorului anterior');
		twAddPortletLink(function(){Twinkle.diff.evaluate(true);}, 'De la a mea', 'tw-sincemine', 'Arată diferența de la ultimul diff și ultima mea versiune' );

		var oldidregex = /oldid=(.+)/.exec(
			$('div#mw-diff-ntitle1 strong a').first().attr("href")
		)
		var oldid = oldidregex ? oldidregex[1] : null;
		if(!oldid) return;
		query = {
			'title': mw.config.get('wgPageName'),
			'diff': 'cur',
			'oldid' : oldid
		};
		twAddPortletLink( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), 'Actual', 'tw-curdiff', 'Arată diferența față de versiunea actuală' );
	}
};

Twinkle.diff.evaluate = function twinklediffEvaluate(me) {
	var ntitle = getElementsByClassName( document.getElementById('bodyContent'), 'td' , 'diff-ntitle' )[0];

	var user;
	if( me ) {
		user = mw.config.get('wgUserName');
	} else {
		var node = document.getElementById( 'mw-diff-ntitle2' );
		if( ! node ) {
			// nothing to do?
			return;
		}
		user = $(node).find('a').first().text();
	}
	var query = {
		'prop': 'revisions',
		'action': 'query',
		'titles': mw.config.get('wgPageName'),
		'rvlimit': 1, 
		'rvprop': [ 'ids', 'user' ],
		'rvstartid': mw.config.get('wgCurRevisionId') - 1, // i.e. not the current one
		'rvuser': user
	};
	Morebits.status.init( document.getElementById('bodyContent') );
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing data of initial contributor', query, Twinkle.diff.callbacks.main );
	wikipedia_api.params = { user: user };
	wikipedia_api.post();
};

Twinkle.diff.callbacks = {
	main: function( self ) {
		var xmlDoc = self.responseXML;
		var revid = $(xmlDoc).find('rev').attr('revid');

		if( ! revid ) {
			self.statelem.error( 'no suitable earlier revision found, or ' + self.params.user + ' is the only contributor. Aborting.' );
			return;
		}
		var query = {
			'title': mw.config.get('wgPageName'),
			'oldid': revid,
			'diff': mw.config.get('wgCurRevisionId')
		};
		window.location = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query );
	}
};

/*
 ****************************************
 *** twinklefluff.js: Revert/rollback module
 ****************************************
 * Mode of invocation:     Links on history, contributions, and diff pages
 * Active on:              Diff pages, history pages, contributions pages
 * Config directives in:   TwinkleConfig
 */

/**
 Twinklefluff revert and antivandalism utility
 */

Twinkle.fluff = {
	auto: function() {
		if( parseInt( Morebits.queryString.get('oldid'), 10) !== mw.config.get('wgCurRevisionId') ) {
			// not latest revision
			alert("Can't rollback, page has changed in the meantime.");
			return;
		}

		var vandal = $("#mw-diff-ntitle2").find("a.mw-userlink").text();

		Twinkle.fluff.revert( Morebits.queryString.get( 'twinklerevert' ), vandal, true );
	},
	normal: function() {

		var spanTag = function( color, content ) {
			var span = document.createElement( 'span' );
			span.style.color = color;
			span.appendChild( document.createTextNode( content ) );
			return span;
		};

		if( mw.config.get('wgNamespaceNumber') === -1 && mw.config.get('wgCanonicalSpecialPageName') === "Contributions" ) {
			//Get the username these contributions are for
			var logLink = $('#contentSub').find('a[title^="Special:Jurnal"]').last();
			if (logLink.length>0) //#215 -- there is no log link on Special:Contributions with no user
			{
				if (mw.config.exists('wgRelevantUserName'))
					var username = mw.config.get('wgRelevantUserName');
				if( Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 ||
					( mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1 ) ||
					( mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1 ) ) {
					var list = $("#mw-content-text").find("ul li:has(span.mw-uctop)");

					var revNode = document.createElement('strong');
					var revLink = document.createElement('a');
					revLink.appendChild( spanTag( 'Black', '[' ) );
					revLink.appendChild( spanTag( 'SteelBlue', 'revenire' ) );
					revLink.appendChild( spanTag( 'Black', ']' ) );
					revNode.appendChild(revLink);

					var revVandNode = document.createElement('strong');
					var revVandLink = document.createElement('a');
					revVandLink.appendChild( spanTag( 'Black', '[' ) );
					revVandLink.appendChild( spanTag( 'Red', 'vandalism' ) );
					revVandLink.appendChild( spanTag( 'Black', ']' ) );
					revVandNode.appendChild(revVandLink);

					list.each(function(key, current) {
						var href = $(current).children("a:eq(1)").attr("href");
						current.appendChild( document.createTextNode(' ') );
						var tmpNode = revNode.cloneNode( true );
						tmpNode.firstChild.setAttribute( 'href', href + '&' + Morebits.queryString.create( { 'twinklerevert': 'norm' } ) );
						current.appendChild( tmpNode );
						current.appendChild( document.createTextNode(' ') );
						tmpNode = revVandNode.cloneNode( true );
						tmpNode.firstChild.setAttribute( 'href', href + '&' + Morebits.queryString.create( { 'twinklerevert': 'vand' } ) );
						current.appendChild( tmpNode );
					});
				}
			}
		} else {
                        
			if( mw.config.get('wgCanonicalSpecialPageName') === "Special:Undelete" ) {
				//You can't rollback deleted pages!
				return;
			}

			var body = document.getElementById('bodyContent');

			var firstRev = $("div.firstrevisionheader").length;
			if( firstRev ) {
				// we have first revision here, nothing to do.
				return;
			}

			var otitle, ntitle;
			try {
				var otitle1 = document.getElementById('mw-diff-otitle1'); 
				var ntitle1 = document.getElementById('mw-diff-ntitle1'); 
				if (!otitle1 || !ntitle1) {
					return;
				}
				otitle = otitle1.parentNode;
				ntitle = ntitle1.parentNode;
			} catch( e ) {
				// no old, nor new title, nothing to do really, return;
				return;
			}

			var old_rev_url = $("div#mw-diff-otitle1 strong a").attr("href");

			// Lets first add a [edit this revision] link
			var query = new Morebits.queryString( old_rev_url.split( '?', 2 )[1] );

			var oldrev = query.get('oldid');

			var revertToRevision = document.createElement('div');
			revertToRevision.setAttribute( 'id', 'tw-revert-to-orevision' );
			revertToRevision.style.fontWeight = 'bold';

			var revertToRevisionLink = revertToRevision.appendChild( document.createElement('a') );
			revertToRevisionLink.href = "#";
			$(revertToRevisionLink).click(function(){
				Twinkle.fluff.revertToRevision(oldrev);
			});
			revertToRevisionLink.appendChild( spanTag( 'Black', '[' ) );
			revertToRevisionLink.appendChild( spanTag( 'SaddleBrown', 'restaurează această versiune' ) );
			revertToRevisionLink.appendChild( spanTag( 'Black', ']' ) );

			otitle.insertBefore( revertToRevision, otitle.firstChild );

			if( document.getElementById('differences-nextlink') ) {
				// Not latest revision
				curVersion = false;

				var new_rev_url = $("div#mw-diff-ntitle1 strong a").attr("href");
				query = new Morebits.queryString( new_rev_url.split( '?', 2 )[1] );
				var newrev = query.get('oldid');
				revertToRevision = document.createElement('div');
				revertToRevision.setAttribute( 'id', 'tw-revert-to-nrevision' );
				revertToRevision.style.fontWeight = 'bold';
				revertToRevisionLink = revertToRevision.appendChild( document.createElement('a') );
				revertToRevisionLink.href = "#";
				$(revertToRevisionLink).click(function(){
					Twinkle.fluff.revertToRevision(newrev);
				});
				revertToRevisionLink.appendChild( spanTag( 'Black', '[' ) );
				revertToRevisionLink.appendChild( spanTag( 'SaddleBrown', 'restaurează această versiune' ) );
				revertToRevisionLink.appendChild( spanTag( 'Black', ']' ) );
				ntitle.insertBefore( revertToRevision, ntitle.firstChild );

				return;
			}
			if( Twinkle.getPref('showRollbackLinks').indexOf('diff') != -1 ) {
				var vandal = $("#mw-diff-ntitle2 a").first().text().replace("'", "\\'");

				var revertNode = document.createElement('div');
				revertNode.setAttribute( 'id', 'tw-revert' );

				var agfNode = document.createElement('strong');
				var vandNode = document.createElement('strong');
				var normNode = document.createElement('strong');

				var agfLink = document.createElement('a');
				var vandLink = document.createElement('a');
				var normLink = document.createElement('a');

				agfLink.href = "#"; 
				vandLink.href = "#"; 
				normLink.href = "#"; 
				$(agfLink).click(function(){
					Twinkle.fluff.revert('agf', vandal);
				});
				$(vandLink).click(function(){
					Twinkle.fluff.revert('vand', vandal);
				});
				$(normLink).click(function(){
					Twinkle.fluff.revert('norm', vandal);
				});

				agfLink.appendChild( spanTag( 'Black', '[' ) );
				agfLink.appendChild( spanTag( 'DarkOliveGreen', 'revenire (BC)' ) );
				agfLink.appendChild( spanTag( 'Black', ']' ) );

				vandLink.appendChild( spanTag( 'Black', '[' ) );
				vandLink.appendChild( spanTag( 'Red', 'revenire (VANDAL)' ) );
				vandLink.appendChild( spanTag( 'Black', ']' ) );

				normLink.appendChild( spanTag( 'Black', '[' ) );
				normLink.appendChild( spanTag( 'SteelBlue', 'revenire' ) );
				normLink.appendChild( spanTag( 'Black', ']' ) );

				agfNode.appendChild(agfLink);
				vandNode.appendChild(vandLink);
				normNode.appendChild(normLink);

				revertNode.appendChild( agfNode );
				revertNode.appendChild( document.createTextNode(' || ') );
				revertNode.appendChild( normNode );
				revertNode.appendChild( document.createTextNode(' || ') );
				revertNode.appendChild( vandNode );

				ntitle.insertBefore( revertNode, ntitle.firstChild );
			}
		}
	}
};

Twinkle.fluff.revert = function revertPage( type, vandal, autoRevert, rev, page ) {

	var pagename = page || mw.config.get('wgPageName');
	var revid = rev || mw.config.get('wgCurRevisionId');
	
	if (mw.util.isIPv6Address(vandal)) {
		vandal = Morebits.sanitizeIPv6(vandal);	
	}

	Morebits.status.init( document.getElementById('bodyContent') );
	var params = {
		type: type,
		user: vandal,
		pagename: pagename,
		revid: revid,
		autoRevert: !!autoRevert
	};
	var query = {
		'action': 'query',
		'prop': ['info', 'revisions'],
		'titles': pagename,
		'rvlimit': 50, // max possible
		'rvprop': [ 'ids', 'timestamp', 'user', 'comment' ],
		'meta': 'tokens'
	};
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing data of earlier revisions', query, Twinkle.fluff.callbacks.main );
	wikipedia_api.params = params;
	wikipedia_api.post();
};

Twinkle.fluff.revertToRevision = function revertToRevision( oldrev ) {

	Morebits.status.init( document.getElementById('bodyContent') );

	var query = {
		'action': 'query',
		'prop': ['info',  'revisions'],
		'titles': mw.config.get('wgPageName'),
		'rvlimit': 1,
		'rvstartid': oldrev,
		'rvprop': [ 'ids', 'timestamp', 'user', 'comment' ],
		'curtimestamp': 1,
		'meta': 'tokens',
		'format': 'xml'
	};
	var wikipedia_api = new Morebits.wiki.api( 'Se aduc datele versiunii anterioare', query, Twinkle.fluff.callbacks.toRevision.main );
	wikipedia_api.params = { rev: oldrev };
	wikipedia_api.post();
};

Twinkle.fluff.userIpLink = function( user ) {
	return (mw.util.isIPAddress(user) ? "[[Special:Contributions/" : "[[User:" ) + user + "|" + user + "]]";
};

Twinkle.fluff.callbacks = {
	toRevision: {
		main: function( self ) {
			var xmlDoc = self.responseXML;

			var lastrevid = parseInt( $(xmlDoc).find('page').attr('lastrevid'), 10);
			var touched = $(xmlDoc).find('page').attr('touched');
			var starttimestamp = $(xmlDoc).find('api').attr('curtimestamp');
			var edittoken = $(xmlDoc).find('tokens').attr('csrftoken');
			var revertToRevID = $(xmlDoc).find('rev').attr('revid');
			var revertToUser = $(xmlDoc).find('rev').attr('user');

			if (revertToRevID !== self.params.rev) {
				self.statitem.error( 'Versiunea obținută nu se potrivește cu cea cerută. Anulat.' );
				return;
			}

			var optional_summary = prompt( "Specificați motivul revenirii:", "" );
			if (optional_summary === null)
			{
				self.statelem.error( 'Oprit de către utilizator.' );
				return;
			}
			var summary = "Revenit la versiunea " + revertToRevID + " a lui " + revertToUser + (optional_summary ? ": " + optional_summary : '') + "." +
				Twinkle.getPref('summaryAd');
		
			var query = { 
				'action': 'edit',
				'title': mw.config.get('wgPageName'),
				'summary': summary,
				'token': edittoken,
				'undo': lastrevid,
				'undoafter': revertToRevID,
				'basetimestamp': touched,
				'starttimestamp': starttimestamp,
				'watchlist': Twinkle.getPref('watchRevertedPages').indexOf( self.params.type ) !== -1 ? 'watch' : undefined,
				'minor': Twinkle.getPref('markRevertedPagesAsMinor').indexOf( self.params.type ) !== -1  ? true : undefined
			};

			Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
			Morebits.wiki.actionCompleted.notice = "Revenire realizată";

			var wikipedia_api = new Morebits.wiki.api( 'Salvez conținutul', query, null/*Twinkle.fluff.callbacks.toRevision.complete*/, self.statelem);
			wikipedia_api.params = self.params;
			wikipedia_api.post();

		},
		complete: function (self) {
		}
	},
	main: function( self ) {
		var xmlDoc = self.responseXML;

		var lastrevid = parseInt( $(xmlDoc).find('page').attr('lastrevid'), 10);
		var touched = $(xmlDoc).find('page').attr('touched');
		var starttimestamp = $(xmlDoc).find('api').attr('curtimestamp');
		var edittoken = $(xmlDoc).find('tokens').attr('csrftoken');
		var lastuser = $(xmlDoc).find('rev').attr('user');

		var revs = $(xmlDoc).find('rev');

		if( revs.length < 1 ) {
			self.statitem.error( 'Nu mai există alte versiuni, deci nu se poate reveni' );
			return;
		}
		var top = revs[0];
		var revertedRevIds = new Array();
		revertedRevIds.push(revs[0].getAttribute('revid'));
		if( lastrevid < self.params.revid ) {
			Morebits.status.error( 'Error', [ 'Cel mai recent ID de versiune primit de la server, ', Morebits.htmlNode( 'strong', lastrevid ), ', este mai mic decât ID-ul versiunii afișate. Probabil că versiunea actuală a fost ștearsă, serverul a dat un răspuns întârziat, sau datele primite sunt eronate. Nu voi continua.' ] );
			return;
		}
		var index = 1;
		if( self.params.revid != lastrevid  ) {
			Morebits.status.warn( 'Warning', [ 'Ultima versiune ', Morebits.htmlNode( 'strong', lastrevid ), ' nu este aceeași cu a noastră ', Morebits.htmlNode( 'strong', self.params.revid ) ] );
			if( lastuser === self.params.user ) {
				switch( self.params.type ) {
				case 'vand':
					Morebits.status.info( 'Info', [ 'Ultima versiune a fost realizată de ', Morebits.htmlNode( 'strong', self.params.user ) , '. Întrucât presupunem că e vandalism, continuăm cu revenirea' ]);
					break;
				case 'agf':
					Morebits.status.warn( 'Warning', [ 'Ultima versiune a fost realizată de ', Morebits.htmlNode( 'strong', self.params.user ) , '. Întrucât presupunem buna credință, nu mai revenim, pentru că probabil s-a rezolvat problema.' ]);
					return;
				default:
					Morebits.status.warn( 'Notice', [ 'Ultima versiune a fost realizată de ', Morebits.htmlNode( 'strong', self.params.user ) , ', dar tot ne oprim din revenire.' ] );
					return;
				}
			}
			else if(self.params.type === 'vand' && 
					Twinkle.fluff.whiteList.indexOf( top.getAttribute( 'user' ) ) !== -1 && revs.length > 1 &&
					revs[1].getAttribute( 'pageId' ) === self.params.revid) {
				Morebits.status.info( 'Info', [ 'Ultima versiune a fost realizată de ', Morebits.htmlNode( 'strong', lastuser ), ', un robot, iar versiunea dinaintea ei aparține vandalului, deci continuăm cu revenirea.' ] );
				index = 2;
			} else {
				Morebits.status.error( 'Error', [ 'Ultima versiune a fost realizată de ', Morebits.htmlNode( 'strong', lastuser ), ', deci poate că s-a făcut deja revenirea, renunțăm la revenire.'] );
				return;
			}

		}

		if( Twinkle.fluff.whiteList.indexOf( self.params.user ) !== -1  ) {
			switch( self.params.type ) {
			case 'vand':
				Morebits.status.info( 'Info', [ 'S-a ales „vandalism” la ', Morebits.htmlNode( 'strong', self.params.user ), '. Acesta este robot înregistrat, deci presupunem că doreați să anulați vandalismul utilizatorului anterior.' ] );
				index = 2;
				vandal = revs[1].getAttribute( 'user' );
				self.params.user = revs[1].getAttribute( 'user' );
				break;
			case 'agf':
				Morebits.status.warn( 'Notice', [ 'S-a ales „bună credință” la ', Morebits.htmlNode( 'strong', self.params.user ), '. Acesta este robot înregistrat, nu are sens genul acesta de revenire, așa că renunțăm.' ] );
				return;
			case 'norm':
				/* falls through */
			default:
				var cont = confirm( 'S-a cerut revenirea normală, dar cele mai recente modificări aparțin unui robot autorizat (' + self.params.user + '). Doriți de fapt să reveniți asupra modificărilor anterioare?' );
				if( cont ) {
					Morebits.status.info( 'Info', [ 'S-a cerut revenirea asupra modificărilor lui ', Morebits.htmlNode( 'strong', self.params.user ), '. Este un robot autorizat, și conform confirmării, revenim asupra modificării anterioare.' ] );
					index = 2;
					self.params.user = revs[1].getAttribute( 'user' );
				} else {
					Morebits.status.warn( 'Notice', [ 'S-a ales revenirea normală asupra modificărilor lui ', Morebits.htmlNode( 'strong', self.params.user ), '. Este un robot autorizat, dar totuși se va continua cu revenirea conform confirmării.' ] );
				}
				break;
			}
		}
		var found = false;
		var count = 0;

		for( var i = index; i < revs.length; ++i ) {
			++count;
			if( revs[i].getAttribute( 'user' ) != self.params.user ) {
				found = i;
				break;
			} else {
				revertedRevIds.push(revs[i].getAttribute('revid'));
			}
		}

		if( ! found ) {
			self.statelem.error( [ 'Nu s-a găsit versiunea anterioară. Este posibil ca ', Morebits.htmlNode( 'strong', self.params.user ), ' să fie unicul autor, sau ca acesta să aibă mai mult de ' + Twinkle.getPref('revertMaxRevisions') + ' modificări consecutive.' ] );
			return;
		}

		if( ! count ) {
			Morebits.status.error( 'Eroare', "Trebuia să revin asupra a zero modificări. Nu are sens, opresc revenirea. Este posibil ca ea să fi fost deja efectuată, dar ID-ul a rămas același." );
			return;
		}

		var good_revision = revs[ found ];
		var userHasAlreadyConfirmedAction = false;
		if (self.params.type !== 'vand' && count > 1) {
			if ( !confirm( self.params.user + ' a efectuat ' + count + ' modificări consecutive. Sunteți sigur că doriți să le înlăturați pe toate?') ) {
				Morebits.status.info( 'Notice', 'Opresc revenirea' );
				return;
			}
			userHasAlreadyConfirmedAction = true;
		}

		self.params.count = count;

		self.params.goodid = good_revision.getAttribute( 'revid' );
		self.params.gooduser = good_revision.getAttribute( 'user' );

		self.statelem.status( [ ' versiunea ', Morebits.htmlNode( 'strong', self.params.goodid ), ' efectuată acum ', Morebits.htmlNode( 'strong', count ), ' versiuni de ', Morebits.htmlNode( 'strong', self.params.gooduser ) ] );

		var summary, extra_summary, userstr, gooduserstr;
		userstr = self.params.user.replace("\\'", "'");

		switch( self.params.type ) {
		case 'agf':
			extra_summary = prompt( "Comentariu opțional pentru sumarul modificării:", "" );
			if (extra_summary === null)
			{
				self.statelem.error( 'Utilizatorul a renunțat.' );
				return;
			}
			userHasAlreadyConfirmedAction = true;

			
			summary = "Revenit asupra modificărilor de [[WP:BC|bună credință]] ale lui [[Special:Contributions/" + userstr + "|" + userstr + "]] ([[Discuție Utilizator:" + 
				userstr + "|D]])" + Twinkle.fluff.formatSummaryPostfix(extra_summary) + Twinkle.getPref('summaryAd');
			break;

		case 'vand':

			gooduserstr = self.params.gooduser.replace("\\'", "'");
			summary = "Revenit asupra a " + self.params.count + (self.params.count > 1 ? ' modificări' : ' modificare') + " a lui [[Special:Contributions/" +
				userstr + "|" + userstr + "]] ([[Discuție Utilizator:" + userstr + "|D]]) " + (self.params.count > 1 ? 'identificate' : 'identificată') + " ca [[WP:V|vandalism]] la ultima versiune a lui " +
				gooduserstr + "." + Twinkle.getPref('summaryAd');
			break;

		case 'norm':
			/* falls through */
		default:
			if( Twinkle.getPref('offerReasonOnNormalRevert') ) {
				extra_summary = prompt( "Comentariu opțional pentru sumarul modificării:", "" );
				if (extra_summary === null)
				{
					self.statelem.error( 'Aborted by user.' );
					return;
				}
				userHasAlreadyConfirmedAction = true;
			}

			summary = "Înlăturat " + self.params.count + (self.params.count > 1 ? ' modificări' : ' modificare') + " a lui [[Special:Contributions/" + 
				userstr + "|" + userstr + "]] ([[Discuție Utilizator:" + userstr + "|D]])" + Twinkle.fluff.formatSummaryPostfix(extra_summary) +
				Twinkle.getPref('summaryAd');
			break;
		}

		if (Twinkle.getPref('confirmOnFluff') && !userHasAlreadyConfirmedAction && !confirm("Înlăturare modificări: sunteți sigur?")) {
			self.statelem.error( 'Utilizatorul a renunțat.' );
			return;
		}

		var query;
		if( (!self.params.autoRevert || Twinkle.getPref('openTalkPageOnAutoRevert')) && 
				Twinkle.getPref('openTalkPage').indexOf( self.params.type ) !== -1 &&
				mw.config.get('wgUserName') !== self.params.user ) {
			Morebits.status.info( 'Info', [ 'Modific pagina de discuție a utilizatorului ', Morebits.htmlNode( 'strong', self.params.user ) ] );
			
			query = {
				'title': 'Discuție Utilizator:' + self.params.user,
				'action': 'edit',
				'preview': 'yes',
				'vanarticle': self.params.pagename.replace(/_/g, ' '),
				'vanarticlerevid': self.params.revid,
				'vanarticlegoodrevid': self.params.goodid,
				'type': self.params.type,
				'count': self.params.count
			};

			switch( Twinkle.getPref('userTalkPageMode') ) {
			case 'tab':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), '_tab' );
				break;
			case 'blank':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
				break;
			case 'window':
				/* falls through */
			default:
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), 'twinklewarnwindow', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
				break;
			}
		}
		
		self.params.revertedRevIds = revertedRevIds;
		
		query = {
			'action': 'edit',
			'title': self.params.pagename,
			'summary': summary,
			'token': edittoken,
			'undo': lastrevid,
			'undoafter': self.params.goodid,
			'basetimestamp': touched,
			'starttimestamp': starttimestamp,
			'watchlist' :  Twinkle.getPref('watchRevertedPages').indexOf( self.params.type ) != -1 ? 'watch' : undefined,
			'minor': Twinkle.getPref('markRevertedPagesAsMinor').indexOf( self.params.type ) != -1  ? true : undefined
		};

		Morebits.wiki.actionCompleted.redirect = self.params.pagename;
		Morebits.wiki.actionCompleted.notice = "Revenire realizată";

		var wikipedia_api = new Morebits.wiki.api( 'Salvez conținutul recuperat din istoric', query, Twinkle.fluff.callbacks.markPatrolled, self.statelem);
		wikipedia_api.params = self.params;
		wikipedia_api.post();

	},
	markPatrolled: function(self) {
		var revertedRevIds = self.params.revertedRevIds;
		if ((Morebits.userIsInGroup('sysop') || Morebits.userIsInGroup('patroller')) && revertedRevIds && revertedRevIds.length > 0) {
			
			var markPatrolledPromises = revertedRevIds.map(function(eachRevId) {
				var api = new mw.Api();
				return api.post( {
					action: 'patrol',
					revid: eachRevId,
					token: mw.user.tokens.get( 'patrolToken' )
				});
			});
			$.when.apply($, markPatrolledPromises).then(function() {
				Twinkle.fluff.callbacks.complete(self);
			}, function() {
				Twinkle.fluff.callbacks.complete(self);
			});
		} else {
			Twinkle.fluff.callbacks.complete(self);
		}
	},
	complete: function (self) {
		self.statelem.info("done");
	}
};

Twinkle.fluff.formatSummaryPostfix = function(stringToAdd) {
	if (stringToAdd) {
		stringToAdd = ': ' + Morebits.string.toUpperCaseFirstChar(stringToAdd);
		if (stringToAdd.search(/[.?!;]$/) == -1) {
			stringToAdd = stringToAdd + '.';
		}
		return stringToAdd;
	}
	else {
		return '.';
	}
};

Twinkle.fluff.init = function twinklefluffinit() {
	if (twinkleUserAuthorized)
	{
		// a list of usernames, usually only bots, that vandalism revert is jumped over, that is
		// if vandalism revert was chosen on such username, then it's target is on the revision before.
		// This is for handeling quick bots that makes edits seconds after the original edit is made.
		// This only affect vandalism rollback, for good faith rollback, it will stop, indicating a bot 
		// has no faith, and for normal rollback, it will rollback that edit.
		Twinkle.fluff.whiteList = [
			'AnomieBOT',
			'ClueBot NG',
			'SineBot'
		];

		if ( Morebits.queryString.exists( 'twinklerevert' ) ) {
			Twinkle.fluff.auto();
		} else {
			Twinkle.fluff.normal();
		}
	}
};

/*
 ****************************************
 *** twinkleimage.js: Image CSD module
 ****************************************
 * Mode of invocation:     Tab ("Imagine")
 * Active on:              File pages with a corresponding file which is local (not on Commons)
 * Config directives in:   TwinkleConfig
 */

Twinkle.image = function twinkleimage() {
	if (mw.config.get('wgNamespaceNumber') === 6 &&
	    !document.getElementById("mw-sharedupload") &&
	    document.getElementById("mw-imagepage-section-filehistory"))
	{
		if(twinkleUserAuthorized) {
			twAddPortletLink(Twinkle.image.callback, "Imagine", "tw-di", "Propune fișier pentru ștergere rapidă cu termen");
		} else {
			twAddPortletLink(function(){
				alert("Contul dumneavoastră este prea recent pentru a folosi Twinkle.");
			}, "Imagine", "tw-di", "Propune fișier pentru ștergere rapidă cu termen");
		}
	}
};

Twinkle.image.callback = function twinkleimageCallback() {
	var Window = new Morebits.simpleWindow( 600, 300 );
	Window.setTitle( "Fișier propus pentru ștergere rapidă cu termen" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Politica de ștergere rapidă", "WP:CȘR" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#image" );

	var form = new Morebits.quickForm( Twinkle.image.callback.evaluate );
	form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Notifică primul uploader',
					value: 'notify',
					name: 'notify',
					tooltip: "Debifați dacă veți face mai multe nominalizări de la același utilizator și nu vreți să-i inundați pagina de discuții cu prea multe notificări.",
					checked: Twinkle.getPref('notifyUserOnDeli')
				}
			]
		}
	);
	var field = form.append( {
			type: 'field',
			label: 'Tip de acțiune'
		} );
	field.append( {
			type: 'radio',
			name: 'type',
			event: Twinkle.image.callback.choice,
			list: [
				{
					label: 'Fără sursă',
					value: 'no source',
					checked: true,
					tooltip: 'Image or media has no source information'
				},
				{
					label: 'Fără licență (CȘR F4)',
					value: 'no license',
					tooltip: 'Image or media does not have information on its copyright status'
				},
				{
					label: 'Fără sursă și fără licență (CȘR F4)',
					value: 'no source no license',
					tooltip: 'Image or media has neither information on source nor its copyright status'
				},
				{
					label: 'Cu utilizare cinstită, nefolosit (CȘR F5)',
					value: 'orphaned fair use',
					tooltip: 'Image or media is unlicensed for use on Wikipedia and allowed only under a claim of fair use per Wikipedia:Non-free content, but it is not used in any articles'
				},
				{
					label: 'Cu utilizare cinstită, nejustificat (CȘR F6)',
					value: 'no fair use rationale',
					tooltip: 'Image or media is claimed to be used under Wikipedia\'s fair use policy but has no explanation as to why it is permitted under the policy'
				},
				{
					label: 'Cu utilizare cinstită, neîncadrată în limitele normale (CȘR F7)',
					value: 'disputed fair use rationale',
					tooltip: 'Image or media has a fair use rationale that is disputed'
				},
				{
					label: 'Cu utilizare cinstită, înlocuibil (CȘR F7)',
					value: 'replaceable fair use',
					tooltip: 'Image or media may fail Wikipedia\'s first non-free content criterion ([[WP:NFCC#1]]) in that it illustrates a subject for which a free image might reasonably be found or created that adequately provides the same information'
				},
				{
					label: 'Fără permisiune (CȘR F11)',
					value: 'no permission',
					tooltip: 'Image or media does not have proof that the author agreed to licence the file'
				}
			]
		} );
	form.append( {
			type: 'div',
			label: 'Work area',
			name: 'work_area'
		} );
	form.append( { type:'submit' } );

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

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

Twinkle.image.callback.choice = function twinkleimageCallbackChoose(event) {
	var value = event.target.values;
	var root = event.target.form;
	var work_area = new Morebits.quickForm.element( {
			type: 'div',
			name: 'work_area'
		} );

	switch( value ) {
		case 'no source no license':
		case 'no source':
			work_area.append( {
					type: 'checkbox',
					name: 'non_free',
					list: [
						{
							label: 'Neliber',
							tooltip: 'Image is licensed under a fair use claim'
						}
					]
				} );
			break;
		case 'no permission':
			work_area.append( {
					type: 'input',
					name: 'source',
					label: 'Sursă: '
				} );
			break;
		case 'disputed fair use rationale':
			work_area.append( {
					type: 'textarea',
					name: 'reason',
					label: 'Problemă: '
				} );
			break;
		case 'orphaned fair use':
			work_area.append( {
					type: 'input',
					name: 'replacement',
					label: 'Înlocuire: '
				} );
			break;
		case 'replaceable fair use':
			work_area.append( {
					type: 'checkbox',
					name: 'old_image',
					list: [
						{
							label: 'Imagine veche',
							tooltip: 'Image was uploaded before 2006-07-13'
						}
					]
				} );
			break;
		default:
			break;
	}

	root.replaceChild( work_area.render(), $(root).find('div[name="work_area"]')[0] );
};

Twinkle.image.callback.evaluate = function twinkleimageCallbackEvaluate(event) {
	var type, non_free, source, reason, replacement, old_image;
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!

	var notify = event.target.notify.checked;
	var types = event.target.type;
	for( var i = 0; i < types.length; ++i ) {
		if( types[i].checked ) {
			type = types[i].value;
			break;
		}
	}
	if( event.target.non_free ) {
		non_free = event.target.non_free.checked;
	}
	if( event.target.source ) {
		source = event.target.source.value;
	}
	if( event.target.reason ) {
		reason = event.target.reason.value;
	}
	if( event.target.replacement ) {
		replacement = event.target.replacement.value;
	}
	if( event.target.old_image ) {
		old_image = event.target.old_image.checked;
	}

	var csdcrit;
	switch( type ) {
		case 'no source no license':
		case 'no source':
		case 'no license':
			csdcrit = "F4";
			break;
		case 'orphaned fair use':
			csdcrit = "F5";
			break;
		case 'no fair use rationale':
			csdcrit = "F6";
			break;
		case 'disputed fair use rationale':
		case 'replaceable fair use':
			csdcrit = "F7";
			break;
		case 'no permission':
			csdcrit = "F11";
			break;
		default:
			throw new Error( "Twinkle.image.callback.evaluate: unknown criterion" );
	}

	var lognomination = Twinkle.getPref('logSpeedyNominations') && Twinkle.getPref('noLogOnSpeedyNomination').indexOf(csdcrit) === -1;

	var params = {
		'type': type,
		'normalized': csdcrit,
		'non_free': non_free,
		'source': source,
		'reason': reason,
		'replacement': replacement,
		'old_image': old_image,
		'lognomination': lognomination
	};
	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( event.target );

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Tagging complete";

	// Tagging image
	var wikipedia_page = new Morebits.wiki.page( mw.config.get('wgPageName'), 'Etichetare fișier' );
	wikipedia_page.setCallbackParameters( params );
	wikipedia_page.load( Twinkle.image.callbacks.taggingImage );

	// Notifying uploader
	if( notify ) {
		wikipedia_page.lookupCreator(Twinkle.image.callbacks.userNotification);
	} else {
		// add to CSD log if desired
		if (lognomination) {
			params.fromDI = true;
			Twinkle.speedy.callbacks.user.addToLog(params, null);
		}
		// No auto-notification, display what was going to be added.
		var noteData = document.createElement( 'pre' );
		noteData.appendChild( document.createTextNode( "{{subst:di-" + type + "-notice|1=" + mw.config.get('wgTitle') + "}} ~~~~" ) );
		Morebits.status.info( 'Notification', [ 'Următoarele date sau altele similare trebuie furnizate uploaderului:', document.createElement( 'br' ),  noteData ] );
	}
};

Twinkle.image.callbacks = {
	taggingImage: function(pageobj) {
		var text = pageobj.getPageText();
		var params = pageobj.getCallbackParameters();

		var tag = "{{di-" + params.type + "|date={{subst:#time:j-m-Y}}";
		switch( params.type ) {
			case 'no source no license':
			case 'no source':
				tag += params.non_free ? "|non-free=yes" : "";
				break;
			case 'no permission':
				tag += params.source ? "|source=" + params.source : "";
				break;
			case 'disputed fair use rationale':
				tag += params.reason ? "|concern=" + params.reason : "";
				break;
			case 'orphaned fair use':
				tag += params.replacement ? "|replacement=" + params.replacement : "";
				break;
			case 'replaceable fair use':
				tag += params.old_image ? "|old image=yes" : "";
				break;
			default:
				break;  // doesn't matter
		}
		tag += "}}\n";

		pageobj.setPageText(tag + text);
		pageobj.setEditSummary("Acest fișier a fost propus pentru ștergere, per [[WP:CȘR#" + params.normalized + "|CȘR " + params.normalized + "]] (" + params.type + ")." + Twinkle.getPref('summaryAd'));
		switch (Twinkle.getPref('deliWatchPage')) {
			case 'yes':
				pageobj.setWatchlist(true);
				break;
			case 'no':
				pageobj.setWatchlistFromPreferences(false);
				break;
			default:
				pageobj.setWatchlistFromPreferences(true);
				break;
		}
		pageobj.setCreateOption('nocreate');
		pageobj.save();
	},
	userNotification: function(pageobj) {
		var params = pageobj.getCallbackParameters();
		var initialContrib = pageobj.getCreator();
		var usertalkpage = new Morebits.wiki.page('Discuție Utilizator:' + initialContrib, "Notificarea contribuitorului inițial (" + initialContrib + ")");
		var notifytext = "\n{{subst:di-" + params.type + "-notice|1=" + mw.config.get('wgTitle');
		if (params.type === 'no permission') {
			notifytext += params.source ? "|source=" + params.source : "";
		}
		notifytext += "}} ~~~~";
		usertalkpage.setAppendText(notifytext);
		usertalkpage.setEditSummary("Notificare: etichetare pentru ștergere [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
		usertalkpage.setCreateOption('recreate');
		switch (Twinkle.getPref('deliWatchUser')) {
			case 'yes':
				usertalkpage.setWatchlist(true);
				break;
			case 'no':
				usertalkpage.setWatchlistFromPreferences(false);
				break;
			default:
				usertalkpage.setWatchlistFromPreferences(true);
				break;
		}
		usertalkpage.setFollowRedirect(true);
		usertalkpage.append();

		// add this nomination to the user's userspace log, if the user has enabled it
		if (params.lognomination) {
			params.fromDI = true;
			Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
		}
	}
};

/*
 ****************************************
 *** twinkleimagetraverse.js: Image traverse module (sysops only)
 ****************************************
 * Mode of invocation:     Tab ("Traverse")
 * Active on:              Categories
 * Config directives in:   TwinkleConfig
 */

Twinkle.imagetraverse = function twinkleimagetraverse() {
	if( Morebits.userIsInGroup( 'sysop' ) && mw.config.get('wgNamespaceNumber') == mw.config.get("wgNamespaceIds").CATEGORY ) {
		twAddPortletLink(Twinkle.imagetraverse.callback, "Traverse", "tw-imagetraverse", "Traverse category");
	}
};

Twinkle.imagetraverse.basequery = {
	'action': 'query',
	'generator': 'categorymembers',
	'gcmtitle': mw.config.get('wgPageName'),
	'gcmnamespace': mw.config.get("wgNamespaceIds").IMAGE,
	'gcmlimit' : 1, 
	'prop': [ 'imageinfo', 'categories', 'revisions' ],
	'rvlimit': 20,
	'iihistory': true,
	'rvprop': [ 'user', 'size', 'flags', 'ids', 'comment', 'timestamp' ],
	'iiprop': [ 'timestamp', 'user', 'url', 'size', 'comment' ]
};
Twinkle.imagetraverse.callback = function() {
	var Window = new Morebits.simpleWindow( 1200, 650 );
	Window.setTitle( "Image traverse" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#imagetraverse" );

	var form = new Morebits.quickForm( Twinkle.imagetraverse.callback.evaluate );
	form.append( {
			type: 'button',
			label: 'Skip',
			event: Twinkle.imagetraverse.callbacks.skip
		} );
	form.append( {
			type: 'button',
			label: 'Delete',
			event: Twinkle.imagetraverse.callbacks.deleteMain
		} );
	form.append( {
			type: 'input',
			label: 'Reason',
			name: 'reason',
			value: 'Speedy deleted',
			size: 80
		} );
	form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Remove image instances to the image',
					name: 'unlink',
					value: 'unlink',
					checked: true
				}
			]
		} );
	var root = document.createElement( 'table' );

	root.style.background = 'transparent';
	root.style.height = '780px';
	var row = root.appendChild( document.createElement( 'tr' ) );
	var options = row.appendChild(  document.createElement( 'td' ) );
	options.setAttribute( 'colspan', 2 );
	var rendered = form.render();
	options.appendChild( rendered );

	rendered.root = root;

	
	options.style.borderBottom = '1px solid gray';
	options.style.height = '80px';
	row = root.appendChild( document.createElement( 'tr' ) );
	var oview = row.appendChild(  document.createElement( 'td' ) );
	var ohistbox = row.appendChild(  document.createElement( 'td' ) );
	ohistbox.style.width = '250px';
	ohistbox.style.verticalAlign = 'top';
	var histbox = ohistbox.appendChild(  document.createElement( 'div' ) );
	histbox.style.overflow = 'auto';
	histbox.style.height = '500px';
	oview.style.verticalAlign = 'top';
	var view = oview.appendChild(  document.createElement( 'div' ) );
	view.style.height = '500px';
	view.style.overflow = 'auto';
	row = root.appendChild( document.createElement( 'tr' ) );
	var ostatus = row.appendChild(  document.createElement( 'td' ) );
	oMorebits.status.style.borderTop = '1px solid gray';
	oMorebits.status.setAttribute( 'colspan', 2 );
	var status = oMorebits.status.appendChild(  document.createElement( 'div' ) );
	oMorebits.status.style.verticalAlign = 'top';
	Morebits.status.style.height = '180px';
	Morebits.status.style.overflow = 'auto';
	Morebits.wiki.actionCompleted.event = function() {}; // just avoid it
	var wikipedia_api = new Morebits.wiki.api( 'Grabbing images', Twinkle.imagetraverse.basequery, Twinkle.imagetraverse.callbacks.main );
	wikipedia_api.params = { root:root, view:view, histbox:histbox, status:status, Window:Window };
	root.params = wikipedia_api.params;
	wikipedia_api.post();

	Morebits.status.init( status );
	Window.setContent( root );
	Window.display();
};

Twinkle.imagetraverse.callback.evaluate = function() {
};

function make_wikilink( page, title, oldid, diff ) {
	var query = {
		'title': page,
		'diff': diff,
		'oldid': oldid
	};
	var url = wgScriptPath + '/index.php?' + Morebits.queryString.create( query );
	var a = document.createElement( 'a' );
	a.setAttribute( 'href', url );
	a.setAttribute( 'title', page );
	a.appendChild( document.createTextNode( title ) );
	return a;
}

Twinkle.imagetraverse.callbacks = {
	main: function( self ) {
		var xmlDoc = self.responseXML;

		var image = xmlDoc.evaluate( '//pages/page/@title', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;

		if( !image ) {
			alert( 'no more images' );
			return;
		}
		var next = xmlDoc.evaluate( '//query-continue/categorymembers/@gcmcontinue', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
		var pagehistory = xmlDoc.evaluate( '//pages/page/revisions/rev', xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
		var filehistory = xmlDoc.evaluate( '//pages/page/imageinfo/ii', xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
		var categories = xmlDoc.evaluate( '//pages/page/categories/cl', xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );

		var pagehistorylist = document.createElement( 'ul' );
		var filehistorylist = document.createElement( 'ul' );
		var categorylist = document.createElement( 'ul' );

		var entry = document.createElement( 'li' );

		var i, cur, tmp, link;
		for( i = 0; i < pagehistory.snapshotLength; ++i ) {
			cur = pagehistory.snapshotItem(i);
			tmp = entry.cloneNode(false);
			tmp.appendChild( make_wikilink( image, cur.getAttribute( 'timestamp' ), cur.getAttribute( 'revid' ) ) );
			tmp.appendChild( document.createTextNode( ' ' ) );
			tmp.appendChild( make_wikilink( 'User:' + cur.getAttribute( 'user' ), cur.getAttribute( 'user' ) ) );
			tmp.appendChild( document.createTextNode( ' (' + ( new Bytes( cur.getAttribute( 'size' ) ) ).toString() + ') (' ) );
			tmp.appendChild( document.createElement( 'em' ) ).appendChild(document.createTextNode( cur.getAttribute( 'comment' ) ) );
			tmp.appendChild( document.createTextNode( ')' ) );
			pagehistorylist.appendChild( tmp );
		}
		
		for( i = 0; i < filehistory.snapshotLength; ++i ) {
			cur = filehistory.snapshotItem(i);
			tmp = entry.cloneNode(false);
			link = document.createElement( 'a' );
			link.setAttribute( 'href', cur.getAttribute( 'url' ) );
			link.appendChild( document.createTextNode( cur.getAttribute( 'timestamp' ) ) );
			tmp.appendChild( link );
			tmp.appendChild( document.createTextNode( ' ' ) );
			tmp.appendChild( make_wikilink( 'User:' + cur.getAttribute( 'user' ), cur.getAttribute( 'user' ) ) );
			tmp.appendChild( document.createTextNode( ' (' + ( new Bytes( cur.getAttribute( 'size' ) ) ).toString() + ') (' ) );
			tmp.appendChild( document.createElement( 'em' ) ).appendChild(document.createTextNode( cur.getAttribute( 'comment' ) ) );
			tmp.appendChild( document.createTextNode( ')' ) );
			filehistorylist.appendChild( tmp );
		}

		for( i = 0; i < categories.snapshotLength; ++i ) {
			cur = categories.snapshotItem(i);
			tmp = entry.cloneNode(false);
			tmp.appendChild( make_wikilink( cur.getAttribute( 'title' ), cur.getAttribute( 'title' ).replace( /Category:/, '' ) ) );
			categorylist.appendChild( tmp );
		}
		self.params.next = next;
		self.params.image = image;
		var hist = self.params.histbox;
		while( hist.hasChildNodes() ) {
			hist.removeChild( hist.lastChild );
		}
		hist.appendChild( document.createElement( 'h2' ) ).appendChild( document.createTextNode( 'Image usage' ) );
		var placeholder = hist.appendChild( document.createElement( 'div' ));
		placeholder.appendChild( document.createTextNode( 'Grabbing data...' ) );
		self.params.imageusageplaceholder = placeholder;
		hist.appendChild( document.createElement( 'h2' ) ).appendChild( document.createTextNode( 'Page history' ) );
		hist.appendChild( pagehistorylist );
		hist.appendChild( document.createElement( 'h2' ) ).appendChild( document.createTextNode( 'File history' ) );
		hist.appendChild( filehistorylist );
		hist.appendChild( document.createElement( 'h2' ) ).appendChild( document.createTextNode( 'Categories' ) );
		hist.appendChild( categorylist );

		var query = {
			'action': 'parse',
			'title': image,
			'text': '{{Wikipedia:WikiProject User scripts/Scripts/Twinkle/Template|' + image.replace(/^File:/, '') + '}}',
			'prop': 'text'
		};
		var wikipedia_api = new Morebits.wiki.api( 'Rendering', query, Twinkle.imagetraverse.callbacks.render1 );
		wikipedia_api.params = self.params;
		wikipedia_api.post();
	},
	render1: function( self ) {
		var xmlDoc = self.responseXML;
		var html = xmlDoc.evaluate( '//parse/text', xmlDoc, null, XPathResult.STRING_TYPE, null ).stringValue;
		self.params.view.innerHTML = html; // gah!

		// add instance usage
		var query = {
			'action': 'query',
			'list': 'imageusage',
			'iutitle': self.params.image,
			'iulimit': 20,
			'iufilterredir': 'nonredirects'
		};
		var wikipedia_api = new Morebits.wiki.api( 'Rendering', query, Twinkle.imagetraverse.callbacks.render2 );
		wikipedia_api.params = self.params;
		wikipedia_api.post();
	},
	render2: function( self ) {
		var xmlDoc = self.responseXML;
		var usage = xmlDoc.evaluate( '//imageusage/iu', xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );

		var usagelist = document.createElement( 'ul' );

		var entry = document.createElement( 'li' );

		for( var i = 0; i < usage.snapshotLength; ++i ) {
			var cur = usage.snapshotItem(i);
			var tmp = entry.cloneNode(false);
			tmp.appendChild( make_wikilink( cur.getAttribute( 'title' ), cur.getAttribute( 'title' ) ) );
			usagelist.appendChild( tmp );
		}
		var hist = self.params.histbox;
		hist.replaceChild( usagelist, self.params.imageusageplaceholder );

	},
	next: function( params ) {
		Twinkle.imagetraverse.basequery.gcmcontinue = params.next;
		var wikipedia_api = new Morebits.wiki.api( 'Grabbing images', Twinkle.imagetraverse.basequery, Twinkle.imagetraverse.callbacks.main );
		wikipedia_api.params = params;
		wikipedia_api.post();
	},
	skip: function( event ) {
		var form = event.target.form;
		var params = form.root.params;
		Twinkle.imagetraverse.callbacks.next( params );
		Morebits.status.info( 'Skipped', params.image );
	},
	deleteMain: function( event ) {
		var form = event.target.form;
		var params = form.root.params;
		params.reason = form.reason.value;

		var query;
		if( form.unlink.checked ) {
			query = {
				'action': 'query',
				'list': 'imageusage',
				'titles': params.image,
				'iulimit': 5000,
				'iufilterredir': 'nonredirects'
			};
			var wikipedia_api = new Morebits.wiki.api( 'Grabbing image links', query, Twinkle.imagetraverse.callbacks.unlinkImageInstancesMain );
			wikipedia_api.params = params;

			wikipedia_api.post();
		}
		var imagepage = new Morebits.wiki.page( params.image, 'șterg fișier');
		imagepage.setEditSummary( "șters deoarece: \"" + params.reason + "\"." + Twinkle.getPref('deletionSummaryAd'));
		imagepage.setCallbackParameters({'image': params.image});
		imagepage.deletePage();
	},
	unlinkImageInstancesMain: function( self ) {
		var xmlDoc = self.responseXML;
		var instances = [];
		$(xmlDoc).find('imageusage iu').each(function(){
			instances.push($(this).attr('title'));
		});
		if( instances.length === 0 ) {
			return;
		}

		$.each( instances, function(k,title) {
			page = new Morebits.wiki.page(title, "Unlinking instances on " + title);
			page.setFollowRedirect(true);
			page.setCallbackParameters({'image': self.params.image, 'reason': self.params.reason});
			page.load(Twinkle.imagetraverse.callbacks.unlinkImageInstances);

		});
	},
	unlinkImageInstances: function( self ) {
		var params = self.getCallbackParameters();
		var statelem = self.getStatusElement();

		var image = params.image.replace( /^(?:Image|File):/, '' );
		var old_text = self.getPageText();
		var wikiPage = new Mediawiki.Page( old_text );
		wikiPage.commentOutImage( image , 'Comentat deoarece imaginea a fost ștearsă' );
		var text = wikiPage.getText();

		if( text === old_text ) {
			statelem.error( 'failed to unlink image ' + image +' from ' + self.getPageName() );
			return;
		}
		self.setPageText(text);
		self.setEditSummary('Elimin utilizare a fișierului ' + image + " ștearsă deoarece: \"" + params.reason + "\")" + "; " + Twinkle.getPref('deletionSummaryAd'));
		self.setCreateOption('nocreate');
		self.save();
	}
};

/*
 ****************************************
 *** twinkleprotect.js: Protect/RPP module
 ****************************************
 * Mode of invocation:     Tab ("PP"/"RPP")
 * Active on:              Non-special pages
 * Config directives in:   TwinkleConfig
 */

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

	if ( Morebits.userIsInGroup( 'sysop' ) ) {
		twAddPortletLink(Twinkle.protect.callback, "PP", "tw-rpp", "Protect page");
	} else if (twinkleUserAuthorized) {
		twAddPortletLink(Twinkle.protect.callback, "RPP", "tw-rpp", "Request page protection");
	} else {
		twAddPortletLink(function() {
			alert("Your account is too new to use Twinkle.");
		}, 'RPP', 'tw-rpp', 'Request page protection');
	}
};

Twinkle.protect.callback = function twinkleprotectCallback() {
	var Window = new Morebits.simpleWindow( 620, 530 );
	Window.setTitle( Morebits.userIsInGroup( 'sysop' ) ? "Apply, request or tag page protection" : "Request or tag page protection" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Protection templates", "Template:Protection templates" );
	Window.addFooterLink( "Protection policy", "WP:PROT" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#protect" );

	var form = new Morebits.quickForm( Twinkle.protect.callback.evaluate );
	var actionfield = form.append( {
			type: 'field',
			label: 'Type of action'
		} );
	if( Morebits.userIsInGroup( 'sysop' ) ) {
		actionfield.append( {
				type: 'radio',
				name: 'actiontype',
				event: Twinkle.protect.callback.changeAction,
				list: [
					{
						label: 'Protect page',
						value: 'protect',
						tooltip: 'Apply actual protection to the page.',
						checked: true
					}
				]
			} );
	}
	actionfield.append( {
			type: 'radio',
			name: 'actiontype',
			event: Twinkle.protect.callback.changeAction,
			list: [
				{
					label: 'Request page protection',
					value: 'request',
					tooltip: 'If you want to request protection via WP:RPP' + (Morebits.userIsInGroup('sysop') ? ' instead of doing the protection by yourself.' : '.'),
					checked: !Morebits.userIsInGroup('sysop')
				},
				{
					label: 'Tag page with protection template',
					value: 'tag',
					tooltip: 'If the protecting admin forgot to apply a protection template, or you have just protected the page without tagging, you can use this to apply the appropriate protection tag.'
				}
			]
		} );

	form.append({ type: 'field', label: 'Preset', name: 'field_preset' });
	form.append({ type: 'field', label: '1', name: 'field1' });
	form.append({ type: 'field', label: '2', name: 'field2' });

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

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

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

	// reduce vertical height of dialog
	$('select[name="editlevel"], select[name="editexpiry"], select[name="moveexpiry"], select[name="movelevel"], select[name="createexpiry"], select[name="createlevel"]').
		parent().css({ display: 'inline-block', marginRight: '0.5em' });

	// get current protection level asynchronously
	Morebits.wiki.actionCompleted.postfix = false;  // avoid Action: completed notice
	if (Morebits.userIsInGroup('sysop')) {
		var query = {
			action: 'query',
			prop: 'info',
			inprop: 'protection',
			titles: mw.config.get('wgPageName')
		};
		Morebits.status.init($('div[name="currentprot"] span').last()[0]);
		var statelem = new Morebits.status("Nivelul actual de protecție");
		var wpapi = new Morebits.wiki.api("retrieving...", query, Twinkle.protect.callback.protectionLevel, statelem);
		wpapi.post();
	}
};

Twinkle.protect.protectionLevel = null;

Twinkle.protect.callback.protectionLevel = function twinkleprotectCallbackProtectionLevel(apiobj) {
	var xml = apiobj.getXML();
	var result = [];
	$(xml).find('pr').each(function(index, pr) {
		var $pr = $(pr);
		var boldnode = document.createElement('b');
		boldnode.textContent = Morebits.string.toUpperCaseFirstChar($pr.attr('type')) + ": " + $pr.attr('level');
		result.push(boldnode);
		if ($pr.attr('expiry') === 'infinity') {
			result.push(" (indefinite) ");
		} else {
			result.push(" (expires " + new Date($pr.attr('expiry')).toUTCString() + ") ");
		}
		if ($pr.attr('cascade') === '') {
			result.push("(cascading) ");
		}
	});
	if (!result.length) {
		var boldnode = document.createElement('b');
		boldnode.textContent = "no protection";
		result.push(boldnode);
	}
	Twinkle.protect.protectionLevel = result;
	apiobj.statelem.info(result);
	window.setTimeout(function() { Morebits.wiki.actionCompleted.postfix = "completed"; }, 500);  // restore actionCompleted message
};

Twinkle.protect.callback.changeAction = function twinkleprotectCallbackChangeAction(e) {
	var field_preset;
	var field1;
	var field2;

	switch (e.target.values) {
		case 'protect':
			field_preset = new Morebits.quickForm.element({ type: 'field', label: 'Preset', name: 'field_preset' });
			field_preset.append({
					type: 'select',
					name: 'category',
					label: 'Choose a preset:',
					event: Twinkle.protect.callback.changePreset,
					list: (mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate)
				});

			field2 = new Morebits.quickForm.element({ type: 'field', label: 'Protection options', name: 'field2' });
			field2.append({ type: 'div', name: 'currentprot', label: ' ' });  // holds the current protection level, as filled out by the async callback
			// for existing pages
			if (mw.config.get('wgArticleId')) {
				field2.append({
						type: 'checkbox',
						name: 'editmodify',
						event: Twinkle.protect.formevents.editmodify,
						list: [
							{
								label: 'Modify edit protection',
								value: 'editmodify',
								tooltip: 'If this is turned off, the edit protection level, and expiry time, will be left as is.',
								checked: true
							}
						]
					});
				var editlevel = field2.append({
						type: 'select',
						name: 'editlevel',
						label: 'Edit protection:',
						event: Twinkle.protect.formevents.editlevel
					});
				editlevel.append({
						type: 'option',
						label: 'All',
						value: 'all'
					});
				editlevel.append({
						type: 'option',
						label: 'Autoconfirmed',
						value: 'autoconfirmed'
					});
				editlevel.append({
						type: 'option',
						label: 'Sysop',
						value: 'sysop',
						selected: true
					});
				field2.append({
						type: 'select',
						name: 'editexpiry',
						label: 'Expires:',
						event: function(e) {
							if (e.target.value === 'custom') {
								Twinkle.protect.doCustomExpiry(e.target);
							}
						},
						list: [
							{ label: '1 hour', value: '1 hour' },
							{ label: '2 hours', value: '2 hours' },
							{ label: '3 hours', value: '3 hours' },
							{ label: '6 hours', value: '6 hours' },
							{ label: '12 hours', value: '12 hours' },
							{ label: '1 day', value: '1 day' },
							{ label: '2 days', selected: true, value: '2 days' },
							{ label: '3 days', value: '3 days' },
							{ label: '4 days', value: '4 days' },
							{ label: '1 week', value: '1 week' },
							{ label: '2 weeks', value: '2 weeks' },
							{ label: '1 month', value: '1 month' },
							{ label: '2 months', value: '2 months' },
							{ label: '3 months', value: '3 months' },
							{ label: '1 year', value: '1 year' },
							{ label: 'indefinite', value:'indefinite' },
							{ label: 'Custom...', value: 'custom' }
						]
					});
				field2.append({
						type: 'checkbox',
						name: 'movemodify',
						event: Twinkle.protect.formevents.movemodify,
						list: [
							{
								label: 'Modify move protection',
								value: 'movemodify',
								tooltip: 'If this is turned off, the move protection level, and expiry time, will be left as is.',
								checked: true
							}
						]
					});
				var movelevel = field2.append({
						type: 'select',
						name: 'movelevel',
						label: 'Move protection:',
						event: Twinkle.protect.formevents.movelevel
					});
				movelevel.append({
						type: 'option',
						label: 'All',
						value: 'all'
					});
				movelevel.append({
						type: 'option',
						label: 'Autoconfirmed',
						value: 'autoconfirmed'
					});
				movelevel.append({
						type: 'option',
						label: 'Sysop',
						value: 'sysop',
						selected: true
					});
				field2.append({
						type: 'select',
						name: 'moveexpiry',
						label: 'Expires:',
						event: function(e) {
							if (e.target.value === 'custom') {
								Twinkle.protect.doCustomExpiry(e.target);
							}
						},
						list: [
							{ label: '1 hour', value: '1 hour' },
							{ label: '2 hours', value: '2 hours' },
							{ label: '3 hours', value: '3 hours' },
							{ label: '6 hours', value: '6 hours' },
							{ label: '12 hours', value: '12 hours' },
							{ label: '1 day', value: '1 day' },
							{ label: '2 days', selected: true, value: '2 days' },
							{ label: '3 days', value: '3 days' },
							{ label: '4 days', value: '4 days' },
							{ label: '1 week', value: '1 week' },
							{ label: '2 weeks', value: '2 weeks' },
							{ label: '1 month', value: '1 month' },
							{ label: '2 months', value: '2 months' },
							{ label: '3 months', value: '3 months' },
							{ label: '1 year', value: '1 year' },
							{ label: 'indefinite', value:'indefinite' },
							{ label: 'Custom...', value: 'custom' }
						]
					});
			} else {  // for non-existing pages
				var createlevel = field2.append({
						type: 'select',
						name: 'createlevel',
						label: 'Create protection:',
						event: Twinkle.protect.formevents.createlevel
					});
				createlevel.append({
						type: 'option',
						label: 'All (registered users)',
						value: 'all'
					});
				createlevel.append({
						type: 'option',
						label: 'Autoconfirmed',
						value: 'autoconfirmed'
					});
				createlevel.append({
						type: 'option',
						label: 'Sysop',
						value: 'sysop',
						selected: true
					});
				field2.append({
						type: 'select',
						name: 'createexpiry',
						label: 'Expires:',
						event: function(e) {
							if (e.target.value === 'custom') {
								Twinkle.protect.doCustomExpiry(e.target);
							}
						},
						list: [
							{ label: '1 hour', value: '1 hour' },
							{ label: '2 hours', value: '2 hours' },
							{ label: '3 hours', value: '3 hours' },
							{ label: '6 hours', value: '6 hours' },
							{ label: '12 hours', value: '12 hours' },
							{ label: '1 day', value: '1 day' },
							{ label: '2 days', value: '2 days' },
							{ label: '3 days', value: '3 days' },
							{ label: '4 days', value: '4 days' },
							{ label: '1 week', value: '1 week' },
							{ label: '2 weeks', value: '2 weeks' },
							{ label: '1 month', value: '1 month' },
							{ label: '2 months', value: '2 months' },
							{ label: '3 months', value: '3 months' },
							{ label: '1 year', value: '1 year' },
							{ label: 'indefinite', selected: true, value: 'indefinite' },
							{ label: 'Custom...', value: 'custom' }
						]
					});
			}
			field2.append({
					type: 'textarea',
					name: 'reason',
					label: 'Protection reason (for log):'
				});
			if (!mw.config.get('wgArticleId')) {  // tagging isn't relevant for non-existing pages
				break;
			}
			/* falls through */
		case 'tag':
			field1 = new Morebits.quickForm.element({ type: 'field', label: 'Tagging options', name: 'field1' });
			field1.append( {
					type: 'select',
					name: 'tagtype',
					label: 'Choose protection template:',
					list: Twinkle.protect.protectionTags,
					event: Twinkle.protect.formevents.tagtype
				} );
			field1.append( {
					type: 'checkbox',
					list: [
						{
							name: 'small',
							label: 'Iconify (small=yes)',
							tooltip: 'Will use the |small=yes feature of the template, and only render it as a keylock',
							checked: true
						},
						{
							name: 'noinclude',
							label: 'Wrap protection template with <noinclude>',
							tooltip: 'Will wrap the protection template in &lt;noinclude&gt; tags, so that it won\'t transclude',
							checked: (mw.config.get('wgNamespaceNumber') === 10)
						}
					]
				} );
			break;

		case 'request':
			field_preset = new Morebits.quickForm.element({ type: 'field', label: 'Type of protection', name: 'field_preset' });
			field_preset.append({
					type: 'select',
					name: 'category',
					label: 'Type and reason:',
					event: Twinkle.protect.callback.changePreset,
					list: (mw.config.get('wgArticleId') ? Twinkle.protect.protectionTypes : Twinkle.protect.protectionTypesCreate)
				});

			field1 = new Morebits.quickForm.element({ type: 'field', label: 'Options', name: 'field1' });
			field1.append( {
					type: 'select',
					name: 'expiry',
					label: 'Duration: ',
					list: [
						{ label: 'Temporary', value: 'temporary' },
						{ label: 'Indefinite', value: 'indefinite' },
						{ label: '', selected: true, value: '' }
					]
				} );
			field1.append({
					type: 'textarea',
					name: 'reason',
					label: 'Reason: '
				});
			break;
		default:
			alert("Something's afoot in twinkleprotect");
			break;
	}

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

	// re-add protection level text, if it's available
	if (e.target.values === 'protect' && Twinkle.protect.protectionLevel) {
		Morebits.status.init($('div[name="currentprot"] span').last()[0]);
		Morebits.status.info("Current protection level", Twinkle.protect.protectionLevel);
	}
};

Twinkle.protect.formevents = {
	editmodify: function twinkleprotectFormEditmodifyEvent(e) {
		e.target.form.editlevel.disabled = !e.target.checked;
		e.target.form.editexpiry.disabled = !e.target.checked || (e.target.form.editlevel.value === 'all');
		e.target.form.editlevel.style.color = e.target.form.editexpiry.style.color = (e.target.checked ? "" : "transparent");
	},
	editlevel: function twinkleprotectFormEditlevelEvent(e) {
		e.target.form.editexpiry.disabled = (e.target.value === 'all');
	},
	movemodify: function twinkleprotectFormMovemodifyEvent(e) {
		e.target.form.movelevel.disabled = !e.target.checked;
		e.target.form.moveexpiry.disabled = !e.target.checked || (e.target.form.movelevel.value === 'all');
		e.target.form.movelevel.style.color = e.target.form.moveexpiry.style.color = (e.target.checked ? "" : "transparent");
	},
	movelevel: function twinkleprotectFormMovelevelEvent(e) {
		e.target.form.moveexpiry.disabled = (e.target.value === 'all');
	},
	createlevel: function twinkleprotectFormCreatelevelEvent(e) {
		e.target.form.createexpiry.disabled = (e.target.value === 'all');
	},
	tagtype: function twinkleprotectFormTagtypeEvent(e) {
		e.target.form.small.disabled = e.target.form.noinclude.disabled = (e.target.value === 'none') || (e.target.value === 'noop');
	}
};

Twinkle.protect.doCustomExpiry = function twinkleprotectDoCustomExpiry(target) {
	var custom = prompt('Enter a custom expiry time.  \nYou can use relative times, like "1 minute" or "19 days", or absolute timestamps, "yyyymmddhhmm" (e.g. "200602011406" is Feb 1, 2006, at 14:06 UTC).', '');
	if (custom) {
		var option = document.createElement('option');
		option.setAttribute('value', custom);
		option.textContent = custom;
		target.appendChild(option);
		target.value = custom;
	}
};

Twinkle.protect.protectionTypes = [
	{
		label: 'Full protection',
		list: [
			{ label: 'Generic (full)', value: 'pp-protected' },
			{ label: 'Content dispute/edit warring (full)', selected: Morebits.userIsInGroup('sysop'), value: 'pp-dispute' },
			{ label: 'Persistent vandalism (full)', value: 'pp-vandalism' },
			{ label: 'Highly visible template (full)', value: 'pp-template' },
			{ label: 'User talk of blocked user (full)', value: 'pp-usertalk' }
		]
	},
	{
		label: 'Semi-protection',
		list: [
			{ label: 'Generic (semi)', value: 'pp-semi-protected' },
			{ label: 'Persistent vandalism (semi)', selected: !Morebits.userIsInGroup('sysop'), value: 'pp-semi-vandalism' },
			{ label: 'BLP policy violations (semi)', value: 'pp-semi-blp' },
			{ label: 'Sockpuppetry (semi)', value: 'pp-semi-sock' },
			{ label: 'Highly visible template (semi)', value: 'pp-semi-template' },
			{ label: 'User talk of blocked user (semi)', value: 'pp-semi-usertalk' }
		]
	},
	{
		label: 'Move protection',
		list: [
			{ label: 'Generic (move)', value: 'pp-move' },
			{ label: 'Dispute/move warring (move)', value: 'pp-move-dispute' },
			{ label: 'Page-move vandalism (move)', value: 'pp-move-vandalism' },
			{ label: 'Highly visible page (move)', value: 'pp-move-indef' }
		]
	},
	{ label: 'Unprotection', value: 'unprotect' }
];

Twinkle.protect.protectionTypesCreate = [
	{
		label: 'Create protection',
		list: [
			{ label: 'Generic ({{pp-create}})', value: 'pp-create' },
			{ label: 'Offensive name', value: 'pp-create-offensive' },
			{ label: 'Repeatedly recreated', selected: true, value: 'pp-create-salt' },
			{ label: 'Recently deleted BLP', value: 'pp-create-blp' }
		]
	},
	{ label: 'Unprotection', value: 'unprotect' }
];

// NOTICE: keep this synched with [[MediaWiki:Protect-dropdown]]
Twinkle.protect.protectionPresetsInfo = {
	'pp-protected': {
		edit: 'sysop',
		move: 'sysop',
		reason: null
	},
	'pp-dispute': {
		edit: 'sysop',
		move: 'sysop',
		reason: '[[WP:PP#Content disputes|Edit warring / Content dispute]]'
	},
	'pp-vandalism': {
		edit: 'sysop',
		move: 'sysop',
		reason: 'Persistent [[WP:Vandalism|vandalism]]'
	},
	'pp-template': {
		edit: 'sysop',
		move: 'sysop',
		reason: '[[WP:High-risk templates|Highly visible template]]'
	},
	'pp-usertalk': {
		edit: 'sysop',
		move: 'sysop',
		reason: '[[WP:PP#Talk-page protection|Inappropriate use of user talk page while blocked]]'
	},
	'pp-semi-vandalism': {
		edit: 'autoconfirmed',
		reason: 'Persistent [[WP:Vandalism|vandalism]]',
		template: 'pp-vandalism'
	},
	'pp-semi-blp': {
		edit: 'autoconfirmed',
		reason: 'Violations of the [[WP:Biographies of living persons|biographies of living persons policy]]'
	},
	'pp-semi-usertalk': {
		edit: 'autoconfirmed',
		move: 'sysop',
		reason: '[[WP:PP#Talk-page protection|Inappropriate use of user talk page while blocked]]'
	},
	'pp-semi-template': {
		edit: 'autoconfirmed',
		move: 'sysop',
		reason: '[[WP:High-risk templates|Highly visible template]]',
		template: 'pp-template'
	},
	'pp-semi-sock': {
		edit: 'autoconfirmed',
		reason: 'Persistent [[WP:Sock puppetry|sock puppetry]]'
	},
	'pp-semi-protected': {
		edit: 'autoconfirmed',
		reason: null,
		template: 'pp-protected'
	},
	'pp-move': {
		move: 'sysop',
		reason: null
	},
	'pp-move-dispute': {
		move: 'sysop',
		reason: '[[WP:MOVP|Move warring]]'
	},
	'pp-move-vandalism': {
		move: 'sysop',
		reason: '[[WP:MOVP|Page-move vandalism]]'
	},
	'pp-move-indef': {
		move: 'sysop',
		reason: '[[WP:MOVP|Highly visible page]]'
	},
	'unprotect': {
		edit: 'all',
		move: 'all',
		create: 'all',
		reason: null,
		template: 'none'
	},
	'pp-create-offensive': {
		create: 'sysop',
		reason: '[[WP:SALT|Offensive name]]'
	},
	'pp-create-salt': {
		create: 'sysop',
		reason: '[[WP:SALT|Repeatedly recreated]]'
	},
	'pp-create-blp': {
		create: 'sysop',
		reason: '[[WP:BLPDEL|Recently deleted BLP]]'
	},
	'pp-create': {
		create: 'sysop',
		reason: '{{pp-create}}'
	}
};

Twinkle.protect.protectionTags = [
	{
		label: 'None (remove existing protection templates)',
		value: 'none'
	},
	{
		label: 'None (do not remove existing protection templates)',
		value: 'noop'
	},
	{
		label: 'Full protection templates',
		list: [
			{ label: '{{pp-dispute}}: dispute/edit war', value: 'pp-dispute', selected: true },
			{ label: '{{pp-usertalk}}: blocked user talk', value: 'pp-usertalk' }
		]
	},
	{
		label: 'Full/semi-protection templates',
		list: [
			{ label: '{{pp-vandalism}}: vandalism', value: 'pp-vandalism' },
			{ label: '{{pp-template}}: high-risk template', value: 'pp-template' },
			{ label: '{{pp-protected}}: general protection', value: 'pp-protected' }
		]
	},
	{
		label: 'Semi-protection templates',
		list: [
			{ label: '{{pp-semi-usertalk}}: blocked user talk', value: 'pp-semi-usertalk' },
			{ label: '{{pp-semi-sock}}: sockpuppetry', value: 'pp-semi-sock' },
			{ label: '{{pp-semi-blp}}: BLP violations', value: 'pp-semi-blp' },
			{ label: '{{pp-semi-indef}}: general long-term', value: 'pp-semi-indef' }
		]
	},
	{
		label: 'Move protection templates',
		list: [
			{ label: '{{pp-move-dispute}}: dispute/move war', value: 'pp-move-dispute' },
			{ label: '{{pp-move-vandalism}}: page-move vandalism', value: 'pp-move-vandalism' },
			{ label: '{{pp-move-indef}}: general long-term', value: 'pp-move-indef' },
			{ label: '{{pp-move}}: other', value: 'pp-move' }
		]
	}
];

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

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

	if (actiontype === 'protect') {  // actually protecting the page
		var item = Twinkle.protect.protectionPresetsInfo[form.category.value];
		if (mw.config.get('wgArticleId')) {
			if (item.edit) {
				form.editmodify.checked = true;
				Twinkle.protect.formevents.editmodify({ target: form.editmodify });
				form.editlevel.value = item.edit;
				Twinkle.protect.formevents.editlevel({ target: form.editlevel });
			} else {
				form.editmodify.checked = false;
				Twinkle.protect.formevents.editmodify({ target: form.editmodify });
			}

			if (item.move) {
				form.movemodify.checked = true;
				Twinkle.protect.formevents.movemodify({ target: form.movemodify });
				form.movelevel.value = item.move;
				Twinkle.protect.formevents.movelevel({ target: form.movelevel });
			} else {
				form.movemodify.checked = false;
				Twinkle.protect.formevents.movemodify({ target: form.movemodify });
			}
		} else {
			if (item.create) {
				form.createlevel.value = item.create;
				Twinkle.protect.formevents.createlevel({ target: form.createlevel });
			}
		}

		if (item.reason) {
			form.reason.value = item.reason;
		} else {
			form.reason.value = '';
		}

		// sort out tagging options
		if (mw.config.get('wgArticleId')) {
			if( form.category.value === 'unprotect' ) {
				form.tagtype.value = 'none';
			} else {
				form.tagtype.value = (item.template ? item.template : form.category.value);
			}
			Twinkle.protect.formevents.tagtype({ target: form.tagtype });

			if( /template/.test( form.category.value ) ) {
				form.noinclude.checked = true;
				form.editexpiry.value = form.moveexpiry.value = "indefinite";
			} else {
				form.noinclude.checked = false;
			}
		}

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

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

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

	if( actiontype === 'tag' || actiontype === 'protect' ) {
		tagparams = {
			tag: form.tagtype.value,
			reason: ((form.tagtype.value === 'pp-protected' || form.tagtype.value === 'pp-semi-protected' || form.tagtype.value === 'pp-move') && form.reason) ? form.reason.value : null,
			expiry: (actiontype === 'protect') ? (form.editmodify.checked ? form.editexpiry.value : (form.movemodify.checked ?
				form.moveexpiry.value : null)) : null,
				small: form.small.checked,
				noinclude: form.noinclude.checked
		};
	}

	switch (actiontype) {
		case 'protect':
			// protect the page
			var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'), "Protecting page");
			if (mw.config.get('wgArticleId')) {
				if (form.editmodify.checked) {
					thispage.setEditProtection(form.editlevel.value, form.editexpiry.value);
				}
				if (form.movemodify.checked) {
					thispage.setMoveProtection(form.movelevel.value, form.moveexpiry.value);
				}
			} else {
				thispage.setCreateProtection(form.createlevel.value, form.createexpiry.value);
			}
			if (form.reason.value) {
				thispage.setEditSummary(form.reason.value);
			} else {
				alert("You must enter a protect reason, which will be inscribed into the protection log.");
				return;
			}

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

			Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
			Morebits.wiki.actionCompleted.notice = "Protection complete";

			thispage.protect();
			/* falls through */
		case 'tag':

			if (actiontype === 'tag') {
				Morebits.simpleWindow.setButtonsEnabled( false );
				Morebits.status.init( form );
				Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
				Morebits.wiki.actionCompleted.followRedirect = false;
				Morebits.wiki.actionCompleted.notice = "Tagging complete";
			}

			if (tagparams.tag === 'noop') {
				Morebits.status.info("Applying protection template", "nothing to do");
				break;
			}

			var protectedPage = new Morebits.wiki.page( mw.config.get('wgPageName'), 'Tagging page');
			protectedPage.setCallbackParameters( tagparams );
			protectedPage.load( Twinkle.protect.callbacks.taggingPage );
			break;

		case 'request':
			// file request at RPP
			var typename, typereason;
			switch( form.category.value ) {
				case 'pp-dispute':
				case 'pp-vandalism':
				case 'pp-template':
				case 'pp-usertalk':
				case 'pp-protected':
					typename = 'full protection';
					break;
				case 'pp-semi-vandalism':
				case 'pp-semi-usertalk':
				case 'pp-semi-template':
				case 'pp-semi-sock':
				case 'pp-semi-blp':
				case 'pp-semi-protected':
					typename = 'semi-protection';
					break;
				case 'pp-move':
				case 'pp-move-dispute':
				case 'pp-move-indef':
				case 'pp-move-vandalism':
					typename = 'move protection';
					break;
				case 'pp-create':
				case 'pp-create-offensive':
				case 'pp-create-blp':
				case 'pp-create-salt':
					typename = 'create protection';
					break;
				case 'unprotect':
					/* falls through */
				default:
					typename = 'unprotection';
					break;
			}
			switch (form.category.value) {
				case 'pp-dispute':
					typereason = 'Content dispute/edit warring';
					break;
				case 'pp-vandalism':
				case 'pp-semi-vandalism':
					typereason = 'Persistent vandalism';
					break;
				case 'pp-template':
				case 'pp-semi-template':
					typereason = 'Highly visible template';
					break;
				case 'pp-usertalk':
				case 'pp-semi-usertalk':
					typereason = 'Inappropriate use of user talk page while blocked';
					break;
				case 'pp-semi-sock':
					typereason = 'Persistent sockpuppetry';
					break;
				case 'pp-semi-blp':
					typereason = '[[WP:BLP|BLP]] policy violations';
					break;
				case 'pp-move-dispute':
					typereason = 'Page title dispute/move warring';
					break;
				case 'pp-move-vandalism':
					typereason = 'Page-move vandalism';
					break;
				case 'pp-move-indef':
					typereason = 'Highly visible page';
					break;
				case 'pp-create-offensive':
					typereason = 'Offensive name';
					break;
				case 'pp-create-blp':
					typereason = 'Recently deleted [[WP:BLP|BLP]]';
					break;
				case 'pp-create-salt':
					typereason = 'Repeatedly recreated';
					break;
				default:
					typereason = '';
					break;
			}

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

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

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

			rppName = 'Wikipedia:Requests for page protection';

			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = rppName;
			Morebits.wiki.actionCompleted.notice = "Nomination completed, redirecting now to the discussion page";

			var rppPage = new Morebits.wiki.page( rppName, 'Requesting protection of page');
			rppPage.setFollowRedirect( true );
			rppPage.setCallbackParameters( rppparams );
			rppPage.load( Twinkle.protect.callbacks.fileRequest );
			break;
		default:
			alert("twinkleprotect: unknown kind of action");
			break;
	}
};

Twinkle.protect.callbacks = {
	taggingPage: function( protectedPage ) {
		var params = protectedPage.getCallbackParameters();
		var text = protectedPage.getPageText();
		var tag, summary;

		var oldtag_re = /\s*(?:<noinclude>)?\s*\{\{\s*(pp-[^{}]*?|protected|(?:t|v|s|p-|usertalk-v|usertalk-s|sb|move)protected(?:2)?|protected template|privacy protection)\s*?\}\}\s*(?:<\/noinclude>)?\s*/gi;

		text = text.replace( oldtag_re, '' );

		if ( params.tag !== 'none' ) {
			tag = params.tag;
			if( params.reason ) {
				tag += '|reason=' + params.reason;
			}
			if( ['indefinite', 'infinite', 'never', null].indexOf(params.expiry) === -1 ) {
				tag += '|expiry={{subst:#time:F j, Y|' + (/^\s*\d+\s*$/.exec(params.expiry) ? params.expiry : '+' + params.expiry) + '}}';
			}
			if( params.small ) {
				tag += '|small=yes';
			}
		}

		if( params.tag === 'none' ) {
			summary = 'Removing protection template' + Twinkle.getPref('summaryAd');
		} else {
			if( params.noinclude ) {
				text = "<noinclude>{{" + tag + "}}</noinclude>" + text;
			} else {
				text = "{{" + tag + "}}\n" + text;
			}
			summary = "Adaug {{" + params.tag + "}}" + Twinkle.getPref('summaryAd');
		}

		protectedPage.setEditSummary( summary );
		protectedPage.setPageText( text );
		protectedPage.setCreateOption( 'nocreate' );
		protectedPage.save();
	},

	fileRequest: function( rppPage ) {

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

		var ns2tag = {
			'0': 'la',
			'1': 'lat',
			'2': 'lu',
			'3': 'lut',
			'4': 'lw',
			'5': 'lwt',
			'6': 'lf',
			'7': 'lft',
			'8': 'lm',
			'9': 'lmt',
			'10': 'lt',
			'11': 'ltt',
			'12': 'lh',
			'13': 'lht',
			'14': 'lc',
			'15': 'lct',
			'100': 'lp',
			'101': 'lpt',
			'108': 'lb',
			'109': 'lbt'
		};

		var rppRe = new RegExp( '====\\s*\\{\\{\\s*' + ns2tag[ mw.config.get('wgNamespaceNumber') ] + '\\s*\\|\\s*' + RegExp.escape( mw.config.get('wgTitle'), true ) + '\\s*\\}\\}\\s*====', 'm' );
		var tag = rppRe.exec( text );

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

		if ( tag ) {
			statusElement.error( [ 'There is already a protection request for this page at ', rppLink, ', aborting.' ] );
			return;
		}

		var newtag = '==== {{' + ns2tag[ mw.config.get('wgNamespaceNumber') ] + '|' + mw.config.get('wgTitle') +  '}} ====' + "\n";
		if( ( new RegExp( '^' + RegExp.escape( newtag ).replace( /\s+/g, '\\s*' ), 'm' ) ).test( text ) ) {
			statusElement.error( [ 'There is already a protection request for this page at ', rppLink, ', aborting.' ] );
			return;
		}

		var words;
		switch( params.expiry ) {
		case 'temporary':
			words = "Temporary ";
			break;
		case 'indefinite':
			words = "Indefinite ";
			break;
		default:
			words = "";
			break;
		}

		words += params.typename;

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

		var reg;
		if ( params.category === 'unprotect' ) {
			reg = /(\n==\s*Current requests for unprotection\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)/;
		} else {
			reg = /(\n==\s*Current requests for protection\s*==\s*\n\s*\{\{[^\}\}]+\}\}\s*\n)/;
		}
		var originalTextLength = text.length;
		text = text.replace( reg, "$1" + newtag + "\n");
		if (text.length === originalTextLength)
		{
			statusElement.error( 'Could not find relevant "current requests for ..." heading on WP:RFPP. Aborting.' );
			return;
		}
		statusElement.status( 'Adding new request...' );
		rppPage.setEditSummary( "Requesting " + params.typename + ' of [[' + mw.config.get('wgPageName').replace(/_/g, ' ') + ']].' + Twinkle.getPref('summaryAd') );
		rppPage.setPageText( text );
		rppPage.setCreateOption( 'recreate' );
		rppPage.save();
	}
};

/*
 ****************************************
 *** twinklespeedy.js: CSD module
 ****************************************
 * Mode of invocation:     Tab ("CSD")
 * Active on:              Non-special, existing pages
 * Config directives in:   TwinkleConfig
 *
 * NOTE FOR DEVELOPERS:
 *   If adding a new criterion, check out the default values of the CSD preferences
 *   in twinkle.header.js, and add your new criterion to those if you think it would
 *   be good. 
 */

Twinkle.speedy = function twinklespeedy() {
	// Disable on:
	// * special pages
	// * non-existent pages
	if (mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId')) {
		return;
	}

	if ( Morebits.userIsInGroup( 'sysop' ) ) {
		twAddPortletLink(Twinkle.speedy.callback, "CȘR", "tw-csd", "ștergeți pagina conform WP:CȘR");
	} else if (twinkleUserAuthorized) {
		twAddPortletLink(Twinkle.speedy.callback, "CȘR", "tw-csd", "Cereți ștergerea rapidă conform WP:CȘR", "");
	} else {
		twAddPortletLink(function() {
			alert("Aveți contul prea recent pentru a folosi Twinkle.");
		}, 'CȘR', 'tw-csd', 'Cereți ștergerea rapidă conform WP:CȘR');
	}
};

// This function is run when the CSD tab/header link is clicked
Twinkle.speedy.callback = function twinklespeedyCallback() {
	Twinkle.speedy.initDialog(Morebits.userIsInGroup( 'sysop' ) ? Twinkle.speedy.callback.evaluateSysop : Twinkle.speedy.callback.evaluateUser, true);
};

Twinkle.speedy.dialog = null;
// Prepares the speedy deletion dialog and displays it
// Parameters:
//  - callbackfunc: the function to call when the dialog box is submitted
//  - firstTime: is this the first time? (false during a db-multiple run, true otherwise)
//  - content: (optional) a div element in which the form content should be rendered - allows
//    for placing content in an existing dialog box
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc, firstTime, content) {
	var dialog;
	if (!content)
	{
		Twinkle.speedy.dialog = new Morebits.simpleWindow( Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight') );
		dialog = Twinkle.speedy.dialog;
		dialog.setTitle( "Choose criteria for speedy deletion" );
		dialog.setScriptName( "Twinkle" );
		dialog.addFooterLink( "Speedy deletion policy", "WP:CSD" );
		dialog.addFooterLink( "Twinkle help", "WP:TW/DOC#speedy" );
	}

	var form = new Morebits.quickForm( callbackfunc, 'change' );
	if( firstTime && Morebits.userIsInGroup( 'sysop' ) ) {
		form.append( {
				type: 'checkbox',
				list: [
					{
						label: 'Etichetează pagina, nu o șterge',
						value: 'tag_only',
						name: 'tag_only',
						tooltip: 'Dacă vreți doar să o etichetați, nu s-o ștergeți imediat',
						checked : Twinkle.getPref('deleteSysopDefaultToTag'),
						event: function( event ) {
							// enable/disable notify checkbox
							event.target.form.notify.disabled = !event.target.checked;
							event.target.form.notify.checked = event.target.checked;
							// enable/disable talk page checkbox
							if (event.target.form.talkpage) {
								event.target.form.talkpage.disabled = event.target.checked;
								event.target.form.talkpage.checked = !event.target.checked && Twinkle.getPref('deleteTalkPageOnDelete');
							}
							// enable/disable redirects checkbox
							event.target.form.redirects.disabled = event.target.checked;
							event.target.form.redirects.checked = !event.target.checked;
							// enable/disable multiple
							$(event.target.form).find('input[name="csd"][value="multiple"]')[0].disabled = !event.target.checked;
							event.stopPropagation();
						}
					}
				]
			} );
		form.append( { type: 'header', label: 'Opțiuni ștergere' } );
		if (mw.config.get('wgNamespaceNumber') % 2 === 0 && (mw.config.get('wgNamespaceNumber') !== 2 || (/\//).test(mw.config.get('wgTitle')))) {  // hide option for user pages, to avoid accidentally deleting user talk page
			form.append( {
				type: 'checkbox',
				list: [
					{
						label: 'șterge și pagina de discuții',
						value: 'talkpage',
						name: 'talkpage',
						tooltip: "This option deletes the page's talk page in addition. If you choose the F8 (moved to Commons) criterion, this option is ignored and the talk page is *not* deleted.",
						checked: Twinkle.getPref('deleteTalkPageOnDelete'),
						disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
						event: function( event ) {
							event.stopPropagation();
						}
					}
				]
			} );
		}
		form.append( {
				type: 'checkbox',
				list: [
					{
						label: 'șterge și redirecționările',
						value: 'redirects',
						name: 'redirects',
						tooltip: "This option deletes all incoming redirects in addition. Avoid this option for procedural (e.g. move/merge) deletions.",
						checked: true,
						disabled: Twinkle.getPref('deleteSysopDefaultToTag'),
						event: function( event ) {
							event.stopPropagation();
						}
					}
				]
			} );
		form.append( { type: 'header', label: 'Opțiuni etichetare' } );
	}

	// don't show this notification checkbox for db-multiple, as the value is ignored
	// XXX currently not possible to turn off notification when using db-multiple
	if (firstTime) {
		form.append( {
				type: 'checkbox',
				list: [
					{
						label: 'Notificați creatorul paginii',
						value: 'notify',
						name: 'notify',
						tooltip: "A notification template will be placed on the talk page of the creator, IF you have a notification enabled in your Twinkle preferences " +
							"for the criterion you choose AND this box is checked. The creator may be welcomed as well.",
						checked: !Morebits.userIsInGroup( 'sysop' ) || Twinkle.getPref('deleteSysopDefaultToTag'),
						disabled: Morebits.userIsInGroup( 'sysop' ) && !Twinkle.getPref('deleteSysopDefaultToTag'),
						event: function( event ) {
							event.stopPropagation();
						}
					}
				]
			}
		);
	} else {
		form.append( { type:'header', label: 'Etichetez cu {{șr-multiplu}}: Criteriul ' + (Twinkle.speedy.dbmultipleCriteria.length + 1) } );
	}

	if (firstTime) {
		form.append( { type: 'radio', name: 'csd',
			list: [
				{
					label: 'Etichetează cu motive multiple',
					value: 'multiple',
					tooltip: 'Opens a series of further dialogs, allowing you to specify all the criteria you want to tag this page with.',
					disabled: Morebits.userIsInGroup('sysop') && !Twinkle.getPref('deleteSysopDefaultToTag')
				}
			]
		} );
	} else if (Twinkle.speedy.dbmultipleCriteria.length > 0) {
		form.append( { type: 'radio', name: 'csd',
			list: [
				{
					label: 'Încheiat etichetarea',
					value: 'multiple-finish'
				}
			]
		} );
	}

	switch (mw.config.get('wgNamespaceNumber')) {
		case 0:  // article
		case 1:  // talk
			form.append( { type: 'header', label: 'Articole' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.getArticleList(!firstTime) } );
			break;

		case 2:  // user
		case 3:  // user talk
			form.append( { type: 'header', label: 'Pagini de utilizator' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.userList } );
			break;

		case 6:  // file
		case 7:  // file talk
			form.append( { type: 'header', label: 'Fișiere' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.getFileList(!firstTime) } );
			form.append( { type: 'div', label: 'Etichetare pentru CȘR F4 (fără licență), F5 (orfan și utilizare cinstită), F6 (fără justificarea utilizării cinstite), and F11 (fără permisiune) nu se poate face cu tabul "Imagine" Twinkle.' } );
			break;

		//case 10:  // template
		//case 11:  // template talk
			form.append( { type: 'header', label: 'Formate' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.getTemplateList(!firstTime) } );
			break;

		//case 14:  // category
		//case 15:  // category talk
			form.append( { type: 'header', label: 'Categorii' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.categoryList } );
			break;

		//case 100:  // portal
		//case 101:  // portal talk
			form.append( { type: 'header', label: 'Portaluri' } );
			form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.getPortalList(!firstTime) } );
			break;

		default:
			break;
	}

	form.append( { type: 'header', label: 'Criterii generale' } );
	form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.getGeneralList(!firstTime) });

	//form.append( { type: 'header', label: 'Redirecționări' } );
	//form.append( { type: 'radio', name: 'csd', list: Twinkle.speedy.redirectList } );

	var result = form.render();
	if (dialog)
	{
		// render new dialog
		dialog.setContent( result );
		dialog.display();
	}
	else
	{
		// place the form content into the existing dialog box
		content.textContent = ''; // clear children
		content.appendChild(result);
	}
};

// this is a function to allow for db-multiple filtering
Twinkle.speedy.getFileList = function twinklespeedyGetFileList(multiple) {
	var result = [];
	result.push({
		label: 'F1: Fișier redundant',
		value: 'redundantimage',
		tooltip: 'Any file that is a redundant copy, in the same file format and same or lower resolution, of something else on Wikipedia. Likewise, other media that is a redundant copy, in the same format and of the same or lower quality. This does not apply to files duplicated on Wikimedia Commons, because of licence issues; these should be tagged with {{subst:ncd|Image:newname.ext}} or {{subst:ncd}} instead'
	});
	result.push({
		label: 'F2: Fișier gol sau corupt',
		value: 'noimage',
		tooltip: 'Înainte de a șterge un asemenea fișier, asigurați-vă că motorul MediaWiki nu-l poate citi, previzualizând un thumbnail de o altă dimensiune. Aici intră și paginile goale de descriere ale imaginilor aflate la Commons'
	});
	if (!multiple) {
		result.push({
			label: 'F2: Descriere suplimentară inutilă pentru un fișier de la Commons',
			value: 'fpcfail',
			tooltip: 'Imaginile aflate la Commons, dar cu etichete sau informații pe pagina sa de descriere de la Wikipedia în română, nu sunt necesare. (Cum ar fi cazul unei imagini care a candidat la a deveni imagine de calitate, dar nu a fost acceptată.)'
		});
	}
	result.push({
		label: 'F3: Licență greșită',
		value: 'noncom',
		tooltip: 'Fișiere cu licență „permis pentru Wikipedia” „doar pentru utilizare necomercială”, „fără opere derivate” sau „cu permisiunea lui X”. Sunt incluse fișiere aflate sub licență "Non-commercial Creative Commons License". Sunt incluse și fișierele a căror licență este nepotrivită, cum ar fi cele marcate ca având autor decedat de peste 70 de ani, când imaginile sunt mai recente decât atât'
	});
	if (Morebits.userIsInGroup('sysop')) {
		result.push({
			label: 'F4: Fără informații de licențiere',
			value: 'unksource',
			tooltip: 'Fișiere din categoria celor cu sursă necunoscută sau cu licență necunoscută, etichetate în acest sens cu un format de mai mult de șapte zile. Vedeți că uneori puteți găsi sursa în sumarul uploadului.'
		});
		result.push({
			label: 'F5: Fișiere sub copyright, nefolosite',
			value: 'unfree',
			tooltip: 'Fișiere neaflate sub licențe libere sau în domeniul public, neutilizate în vreun articol. O excepție rezonabilă o poate constitui un fișier încărcat pentru un articol în lucru.'
		});
		result.push({
			label: 'F6: Fără justificarea utilizării cinstite',
			value: 'norat',
			tooltip: 'Orice fișier fără o justificare a utilizării cinstite poate fi șters la șapte zile după încărcare. Formatele artizanale de utilizare cinstită nu constituie justificare.'
		});
	}
	result.push({
		label: 'F7: Afirmație incorectă privind utilizarea cinstită',
		value: 'badfairuse',
		tooltip: 'Orice fișier cu etichetă invalidă de utilizare cinstită (cum ar fi eticheta {{logo}} pusă pe fotografia unei mascote) poate fi șters în orice moment. Fișierele care nu respectă oricare dintre criteriile pentru conținutul cu utilizare cinstită pot fi șterse la șapte zile de la notificarea uploaderului.'
	});
	if (!multiple) {
		result.push({
			label: 'F8: Fișier disponibil la Wikimedia Commons',
			value: 'nowcommons',
			tooltip: 'Dacă sunt respectate următoarele condiții: 1: Formatul fișierului este similar. 2: Licența și sursa fișierului sunt sigure și lămurite. 3: Toate informațiile de pe pagina de descriere a fișierului sunt prezente și pe pagina de descriere de la Commons. Aici intră istoricul uploadurilor cu linkuri către pagina de utilizator a autorilor. 4: Fișierul nu este protejat, iar pagina de descriere nu conține vreo cerere justificată de a nu fi transferat la Commons. 5: Dacă fișierul este disponibil la Commons sub un alt nume decât cel local, toate referințele la fișier trebuie actualizate către cea de la Commons.'
		});
	}
	result.push({
		label: 'F9: Încălcare clară a drepturilor de autor',
		value: 'imgcopyvio',
		tooltip: 'Fișierul este copiat de pe un website sau din altă sursă care nu are o licența compatibilă cu Wikipedia, iar uploaderul nu justifică în mod credibil utilizarea cinstită sau existența vreunei posibile permisiuni de utilizare liberă. Fișierele care sunt doar suspecte de încalcare a dreptului de autor (fără a fi clar copiate de undeva) se discută la Wikipedia:Pagini de șters'
	});
	result.push({
		label: 'F10: Fișier inutil',
		value: 'badfiletype',
		tooltip: 'Fișiere care nu sunt nici imagini, nici sunete, nici fișiere video (de exemplu, fișiere de tip .doc, .pdf, sau .xls) care nu sunt utilizate în niciun articol și nu au vreo posibilă utilizare enciclopedică'
	});
	if (Morebits.userIsInGroup('sysop')) {
		result.push({
			label: 'F11: Fără dovada permisiunii',
			value: 'nopermission',
			tooltip: 'Dacă un uploader a specificat o licență și a denumit o terță parte ca deținător al drepturilor de autor sau ca sursă, dar nu a furnizat suficiente dovezi că acea terță parte a acceptat această licențiere, atunci fișierul respectiv se poate șterge la șapte zile de la notificarea uploaderului'
		});
	}
	result.push({
		label: 'G8: Pagină de descriere a unui fișier inexistent',
		value: 'imagepage',
		tooltip: 'This is only for use when the file doesn\'t exist at all. Corrupt files, and local description pages for files on Commons, should use F2; implausible redirects should use R3; and broken Commons redirects should use G6.'
	});
	return result;
};

Twinkle.speedy.getArticleList = function twinklespeedyGetArticleList(multiple) {
	var result = [];
	result.push({
		label: 'A1: Fără context. Articole fără suficient context pentru a identifica subiectul articolului.',
		value: 'nocontext',
		tooltip: 'Example: "He is a funny man with a red car. He makes people laugh." This applies only to very short articles. Context is different from content, treated in A3, below.'
	});
	result.push({
		label: 'A2: Articole în limbi străine de pe alt proiect Wikimedia',
		value: 'foreign',
		tooltip: 'If the article in question does not exist on another project, the template {{notenglish}} should be used instead. All articles in a non-English language that do not meet this criteria (and do not meet any other criteria for speedy deletion) should be listed at Pages Needing Translation (PNT) for review and possible translation'
	});
	result.push({
		label: 'A3: Fără conținut (enciclopedic)',
		value: 'nocontent',
		tooltip: 'Any article consisting only of links elsewhere (including hyperlinks, category tags and "see also" sections), a rephrasing of the title, and/or attempts to correspond with the person or group named by its title. This does not include disambiguation pages'
	});
	result.push({
		label: 'A5: Articol mutat prin Transwiki',
		value: 'transwiki',
		tooltip: 'Any article that has been discussed at Articles for Deletion (et al), where the outcome was to transwiki, and where the transwikification has been properly performed and the author information recorded. Alternately, any article that consists of only a dictionary definition, where the transwikification has been properly performed and the author information recorded'
	});
	result.push({
		label: 'A7: Persoane, grupuri, firme, siteuri și animale oarecare',
		value: 'a7',
		tooltip: 'An article about a real person, group of people, band, club, company, web content, or individual animal that does not assert the importance or significance of its subject. If controversial, or if there has been a previous AfD that resulted in the article being kept, the article should be nominated for AfD instead'
	});
	if (!multiple) {
		result.push({
			label: 'A7: Persoană neremarcabilă',
			value: 'person',
			tooltip: 'An article about a real person that does not assert the importance or significance of its subject. If controversial, or if there has been a previous AfD that resulted in the article being kept, the article should be nominated for AfD instead'
		});
		result.push({
			label: 'A7: Formație sau muzician neremarcabil',
			value: 'band',
			tooltip: 'Article about a band, singer, musician, or musical ensemble that does not assert the importance or significance of the subject'
		});
		result.push({
			label: 'A7: Firmă sau organizație neremarcabilă',
			value: 'corp',
			tooltip: 'Article about a company or organization that does not assert the importance or significance of the subject'
		});
		result.push({
			label: 'A7: Site neremarcabil',
			value: 'web',
			tooltip: 'Article about a web site, blog, online forum, webcomic, podcast, or similar web content that does not assert the importance or significance of its subject'
		});
		result.push({
			label: 'A7: Animal neremarcabil',
			value: 'animal',
			tooltip: 'Article about an individual animal (e.g. pet) that does not assert the importance or significance of its subject'
		});
	}
	result.push({
		label: 'A9: Înregistrare muzicală neremarcabilă a unui artist fără articol',
		value: 'a9',
		tooltip: 'An article about a musical recording which does not indicate why its subject is important or significant, and where the artist\'s article has never existed or has been deleted'
	});
	if (!multiple) {
		result.push({
			label: 'A10: Articol recent creat pe un subiect deja tratat',
			value: 'a10',
			tooltip: 'A recently created article with no relevant page history that does not aim to expand upon, detail or improve information within any existing article(s) on the subject, and where the title is not a plausible redirect. This does not include content forks, split pages or any article that aims at expanding or detailing an existing one.'
		});
		result.push({
			label: 'A11: Articol cu conținut neenciclopedic',
			value: 'a11',
			tooltip: 'Articol recent creat ce conține tratări neenciclopedice ale subiectului lor. Sunt incluse aici eseuri, păreri personale, definiții de dicționar, manuale, articole de presă etc.'
		});
	}
	return result;
};

Twinkle.speedy.categoryList = [
	{
		label: 'C1: Categorii goale',
		value: 'catempty',
		tooltip: '(no articles or subcategories for at least four days) whose only content has consisted of links to parent categories. This does not apply to categories being discussed on WP:CFD or WP:SFD, or disambiguation categories. If the category isn\'t relatively new, it possibly contained articles earlier, and deeper investigation is needed'
	},
	{
		label: 'G8: Categoriii populate de un format șters sau redirecționat',
		value: 'templatecat',
		tooltip: 'If a template which includes pages in a category has been deleted, the associated category can be deleted. This excludes categories that are still in use.'
	}
];

Twinkle.speedy.userList = [
	{
		label: 'U1: La cererea utilizatorului',
		value: 'userreq',
		tooltip: 'Personal subpages, upon request by their user. In some rare cases there may be administrative need to retain the page. Also, sometimes, main user pages may be deleted as well. See Wikipedia:User page for full instructions and guidelines'
	},
	{
		label: 'U2: Utilizator inexistent',
		value: 'nouser',
		tooltip: 'Pagini ale unor utilizatori care nu există (Vedeți Special:Listusers)'
	},
	{
		label: 'U3: Galerii de imagini ne-libere',
		value: 'gallery',
		tooltip: 'Galerii din spațiul Utilizator, formate mai ales din imagini nelibere. Politica de conținut a Wikipediei interzice utilizatorilor să afișeze materiale protejate în spațiul Utilizator. Sunt acceptabile doar materialele libere'
	},
	{
		label: 'U4: Pagini de utilizator fără legătură cu proiectul',
		value: 'notwebhost',
		tooltip: 'CV-uri, autoprezentări ample, reclame etc.'
	}
];

Twinkle.speedy.getTemplateList = function twinklespeedyGetTemplateList(multiple) {
	var result = [];
	result.push({
		label: 'T2: Formate ce reprezintă greșit politica proiectului',
		value: 'policy',
		tooltip: 'This includes "speedy deletion" templates for issues that are not speedy deletion criteria and disclaimer templates intended to be used in articles'
	});
	if (!multiple) {
		result.push({
			label: 'T3: Formate inutile',
			value: 't3',
			tooltip: 'Templates that are either substantial duplications of another template or hardcoded instances of another template where the same functionality could be provided by that other template'
		});
	}
	return result;
};

Twinkle.speedy.getPortalList = function twinklespeedyGetPortalList(multiple) {
	var result = [];
	if (!multiple) {
		result.push({
			label: 'P1: Portal ce ar fi șters rapid dacă ar fi articol',
			value: 'p1',
			tooltip: 'Trebuie să specificați ce criteriu aplicabil articolelor se aplică în acest caz (A1, A3, A7, sau A10).'
		});
	}
	result.push({
		label: 'P2: Portal nepopulat',
		value: 'emptyportal',
		tooltip: 'Any Portal based on a topic for which there is not a non-stub header article, and at least three non-stub articles detailing subject matter that would be appropriate to discuss under the title of that Portal'
	});
	return result;
};

Twinkle.speedy.getGeneralList = function twinklespeedyGetGeneralList(multiple) {
	var result = [];
	if (!multiple) {
		result.push({
			label: 'Explicație specifică:' + (Morebits.userIsInGroup('sysop') ? ' (custom deletion reason)' : ' using {'+'{db}} template'),
			value: 'reason',
			tooltip: '{'+'{șr}} este o prescurtare de la „ștergere rapidă”. Un alt criteriu ar putea fi încă aplicabil și trebie să-l amintiți în justificare. Nu este un caz general pentru când nu știți criteriul.'
		});
	}
	result.push({
		label: 'G1: Text fără sens. Text incoerent fără vreo variantă validă în istoric.',
		value: 'nonsense',
		tooltip: 'This does not include poor writing, partisan screeds, obscene remarks, vandalism, fictional material, material not in English, poorly translated material, implausible theories, or hoaxes'
	});
	result.push({
		label: 'G2: Pagină de test',
		value: 'test',
		tooltip: 'de ex., "Chiar pot să creez o pagină?"'
	});
	result.push({
		label: 'G3: Pur vandalism',
		value: 'vandalism',
		tooltip: 'Candalism curat (inclusiv redirecționări rămase în urma vandalismului cu redenumiri)'
	});
	if (!multiple) {
		result.push({
			label: 'G3: Farsă evidentă',
			value: 'hoax',
			tooltip: 'Farse clare, la limita vandalismului'
		});
	}
	result.push({
		label: 'G4: Recreare a unui material șters',
		value: 'repost',
		tooltip: 'Copie, sub orice titlu, a unui material șters în urma unei discuții, sau o nouă pagină creată pe același subiect ce suferă de aceleași deficiențe care au dus la ștergerea ei în urma unei discuții. Nu se aplică dacă respectivul material a fost șters rapid, deși criteriul care a dus la prima ștergere rapidă se poate aplica din nou'
	});
	result.push({
		label: 'G5: Utilizator cu interdicție',
		value: 'banned',
		tooltip: 'Pagini create de utilizatori cu interdicție cu violarea interdicției'
	});
	if (!multiple) {
		result.push({
			label: 'G6: Unire istoric',
			value: 'histmerge',
			tooltip: 'ștergere temporară pentru unirea sau separarea istoricului'
		});
		result.push({
			label: 'G6: Mutare',
			value: 'move',
			tooltip: 'Making way for a noncontroversial move like reversing a redirect'
		});
		result.push({
			label: 'G6: În urma discuției',
			value: 'xfd',
			tooltip: 'Un administrator a închis o propunere de ștergere, dar nu a șters încă pagina.'
		});
		result.push({
			label: 'G6: Pagină de dezambiguizare inutilă',
			value: 'disambig',
			tooltip: 'This only applies for orphaned disambiguation pages which either: (1) disambiguate two or fewer existing Wikipedia pages and whose title ends in "(disambiguation)" (i.e., there is a primary topic); or (2) disambiguates no (zero) existing Wikipedia pages, regardless of its title.'
		});
		result.push({
			label: 'G6: Redirect spre pagină greșită/inexistentă',
			value: 'g6',
			tooltip: 'This only applies for redirects to wrong pages.'
		});
		result.push({
			label: 'G6: Mutare prin copy-paste',
			value: 'copypaste',
			tooltip: 'This only applies for a copy-and-paste page move of another page that needs to be temporarily deleted to make room for a clean page move.'
		});
	}
	result.push({
		label: 'G6: Mentenanță',
		value: 'g6',
		tooltip: 'Other non-controversial "housekeeping" tasks'
	});
	result.push({
		label: 'G7: Ștergere cerută de autor',
		value: 'author',
		tooltip: 'Any page for which deletion is requested by the original author in good faith, provided the page\'s only substantial content was added by its author. If the author blanks the page, this can also be taken as a deletion request.'
	});
	result.push({
		label: 'G8: Pagini dependente de alte pagini',
		value: 'g8',
		tooltip: 'such as talk pages with no corresponding subject page; subpages with no parent page; file pages without a corresponding file; redirects to invalid targets, such as nonexistent targets, redirect loops, and bad titles; or categories populated by deleted or retargeted templates. This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.'
	});
	if (!multiple) {
		result.push({
			label: 'G8: Pagină de discuție fără pagină principală',
			value: 'talk',
			tooltip: 'Cu excepția paginilor utile pentru proiect, anume: pagini de discuție ale utilizatorilor, arhive ale paginilor de discuție, redirecționări plauzible, pagini de discuție ale fișierelor de la Wikimedia Commons și pagini ce conțin formate de întreținere utile.'
		});
		result.push({
			label: 'G8: Subpagină fără părinte',
			value: 'subpage',
			tooltip: 'This excludes any page that is useful to the project, and in particular: deletion discussions that are not logged elsewhere, user and user talk pages, talk page archives, plausible redirects that can be changed to valid targets, and file pages or talk pages for files that exist on Wikimedia Commons.'
		});
	}
	result.push({
		label: 'G10: Pagină de atac',
		value: 'attack',
		tooltip: 'Pagini care nu au alt scop decât să arunce cu noroi în subiectul lor sau în altă entitate. Aici intră și biografii ale persoanelor în viață scrise fără surse cu un ton negative, în cazul în care nu există în istoric o versiune neutră la care să se revină. Administratorii care șterg asemenea pagini sunt rugați să nu citeze din conținutul paginii în sumarul ștergerii!'
	});
	result.push({
		label: 'G11: Reclamă evidentă',
		value: 'spam',
		tooltip: 'Pages which exclusively promote a company, product, group, service, or person and which would need to be fundamentally rewritten in order to become encyclopedic. Note that simply having a company, product, group, service, or person as its subject does not qualify an article for this criterion; an article that is blatant advertising should have inappropriate content as well'
	});
	result.push({
		label: 'G12: Încălcare evidentă a drepturilor de autor',
		value: 'copyvio',
		tooltip: 'Either: (1) Material was copied from another website that does not have a license compatible with Wikipedia, or is photography from a stock photo seller (such as Getty Images or Corbis) or other commercial content provider; (2) There is no non-infringing content in the page history worth saving; or (3) The infringement was introduced at once by a single person rather than created organically on wiki and then copied by another website such as one of the many Wikipedia mirrors'
	});
	return result;
};

Twinkle.speedy.redirectList = [
	{
		label: 'R2: Redirecționări din spațiul principal spre orice alt spațiu cu excepția spațiilor Categorie:, Format:, Wikipedia:, Ajutor: și Portal:',
		value: 'rediruser',
		tooltip: '(not include și pseudo-spațiile de nume cu rol de scurtătură). Dacă acesta rezultă dintr-o redenumire de pagină, poate mai bine așteptați una-două zile până să ștergeți și redirectul'
	},
	{
		label: 'R3: Redirecționări recent create ca urmare a unei greșeli de tipar improbabile',
		value: 'redirtypo',
		tooltip: 'Cele de la denumiri frecvente sunt în general utile, la fel ca redirecționările din alte limbi; nu sunt însă utile cele de la titlul fără diacritice dacă acestea sunt pur românești'
	},
	{
		label: 'G8: Redirecționări către ținte inexistente, titluri greșite sau bucle de redirecționare',
		value: 'redirnone',
		tooltip: 'Se exclud paginile utile proiectului și în particular: discuțiile despre ștergeri care sunt logate în altă parte, paginile de utilizator și de discuție, arhivele discuțiilor, redirecționări plauzibile ce pot fi schimbate să ducă spre ținte valide, pagini de fișiere și discuție pentru fișiere ce există la Wikimedia Commons.'
	}
];

Twinkle.speedy.normalizeHash = {
	'reason': 'db',
	'multiple': 'multiple',
	'multiple-finish': 'multiple-finish',
	'nonsense': 'g1',
	'test': 'g2',
	'vandalism': 'g3',
	'hoax': 'g3',
	'repost': 'g4',
	'banned': 'g5',
	'histmerge': 'g6',
	'move': 'g6',
	'xfd': 'g6',
	'disambig': 'g6',
	'movedab': 'g6',
	'copypaste': 'g6',
	'g6': 'g6',
	'author': 'g7',
	'g8': 'g8',
	'talk': 'g8',
	'subpage': 'g8',
	'redirnone': 'g8',
	'templatecat': 'g8',
	'attack': 'g10',
	'spam': 'g11',
	'copyvio': 'g12',
	'nocontext': 'a1',
	'foreign': 'a2',
	'nocontent': 'a3',
	'transwiki': 'a5',
	'a7': 'a7',
	'person': 'a7',
	'corp': 'a7',
	'web': 'a7',
	'band': 'a7',
	'animal': 'a7',
	'a9': 'a9',
	'a10': 'a10',
	'a11': 'a11',
	'rediruser': 'r2',
	'redirtypo': 'r3',
	'redundantimage': 'f1',
	'noimage': 'f2',
	'fpcfail': 'f2',
	'noncom': 'f3',
	'unksource': 'f4',
	'unfree': 'f5',
	'norat': 'f6',
	'badfairuse': 'f7',
	'nowcommons': 'f8',
	'imgcopyvio': 'f9',
	'badfiletype': 'f10',
	'nopermission': 'f11',
	'catempty': 'c1',
	'userreq': 'u1',
	'nouser': 'u2',
	'gallery': 'u3',
	'notwebhost': 'u4',
	'policy':'t2',
	't3':'t3',
	'p1':'p1',
	'emptyportal': 'p2'
};

// keep this synched with [[MediaWiki:Deletereason-dropdown]]
Twinkle.speedy.reasonHash = {
	'reason': '',
// General
	'nonsense': '[[WP:CȘR#G1|Conținut fără sens]], sau incomprehensibil',
	'test': 'Teste',
	'vandalism': '[[Wikipedia:Vandalism|Vandalism]]',
	'hoax': 'Farse sau glume',
	'repost': 'Recreare a unei pagini [[Wikipedia:ștergere|șterse]] în urma unei discuții',
	'banned': 'Pagină de utilizator [[Wikipedia:Blocare|blocat]] sau cu interdicție',
	'histmerge': 'ștergere temporară pentru unirea istoricului',
	'move': 'Pentru a permite o mutare',
	'xfd': 'Ștergere în urma unei discuții',
	'disambig': 'Dezambiguizare inutilă',
	'movedab': 'Redirecționare spre dezambiguizare greșit intitulată',
	'copypaste': 'Mutare prin copy-paste',
	'g6': 'Mentenanță',
	'author': 'La cererea unicului autor',
	'g8': 'Pagină dependentă de o pagină ștearsă sau inexistentă',
	'talk': 'Pagina de discuții a unei pagini șterse sau inexistente',
	'subpage': 'Subpagină a unei pagini șterse sau inexistente',
	'redirnone': 'Redirecționare spre o pagină ștearsă sau inexistentă',
	'templatecat': 'Populată de un format șters sau redirecționat',
	'attack': 'Atac la persoană sau [[WP:BPV|BPV]] fără surse',
	'spam': 'Reclamă sau autopromovare',
	'copyvio': 'Încălcarea [[WP:DA|drepturilor de autor]]',
// Articles
	'nocontext': 'Insuficient context pentru a identifica subiectul',
	'foreign': 'Articol într-o limbă străină de pe un alt proiect',
	'nocontent': 'Fără conținut',
	'transwiki': 'Articol mutat prin transwiki la alt proiect',
	'a7': 'Fără explicație a importanței subiectului',
	'person' : 'Fără explicație a importanței subiectului (persoană)',
	'web': 'Fără explicație a importanței subiectului (site web)',
	'corp': 'Fără explicație a importanței subiectului (organizație)',
	'band': 'Fără explicație a importanței subiectului (formație/muzician)',
	'animal': 'Fără explicație a importanței subiectului (animal)',
	'a9': 'Înregistrare muzicală fără indicare a importanței sau a unui artist fără articol ',
	'a10': 'Articol ce tratează un subiect deja tratat',
	'a11': 'Articol cu conținut neenciclopedic',
// Images and media
	'redundantimage': 'Fișier înlocuit de altul la Wikipedia',
	'noimage': 'Fișier corupt sau gol',
	'fpcfail': 'Pagină de descriere inutilă a unui fișier de la Commons',
	'noncom': 'Fișier cu licență greșită',
	'unksource': 'Lipsa informațiilor de licențiere',
	'unfree': 'Fișier neliber nefolosit',
	'norat': 'Fișier non-liber fără [[WP:JUC|justificarea utilizării cinstite]]',
	'badfairuse': 'Afirmație de utilizare cinstită incorectă',
	'nowcommons': 'Fișier disponibil la Commons',
	'imgcopyvio': 'Încălcarea [[WP:DA|drepturilor de autor]]',
	'badfiletype': 'Fișier inutil',
	'nopermission': 'Fără dovada permisiunii',
// Categories
	'catempty': 'Categorie goală',
// User pages
	'userreq': 'La cererea utilizatorului, pagină din spațiul său',
	'nouser': 'Pagină sau subpagină de utilizator inexistent',
	'gallery': 'Galerie ne-liberă',
	'notwebhost': 'Pagină de utilizator fără legătură cu Wikipedia',
// Templates
	'policy': 'Format ce reprezintă greșit politicile',
	't3': 'Format neutilizat, inutil',
// Portals
	'p1': 'Portal ce ar fi șters dacă ar fi articol',
	'emptyportal': 'Portal fără subiect',
// Redirects
	'rediruser': 'Redirecționare cross-[[WP:NS|namespace]]',
	'redirtypo': 'Redirecționare recent creată, implauzibilă'
};

Twinkle.speedy.callbacks = {
	sysop: {
		main: function( params ) {
			var thispage = new Morebits.wiki.page( mw.config.get('wgPageName'), "șterg pagina" );

			// delete page
			var reason;
			if (params.normalized === 'db') {
				reason = prompt("Introduceți descrierea ștergerii:", "");
			} else {
				var presetReason = "[[WP:CSD#" + params.normalized.toUpperCase() + "|" + params.normalized.toUpperCase() + "]]: " + params.reason;
				if (Twinkle.getPref("promptForSpeedyDeletionSummary").indexOf(params.normalized) !== -1) {
					reason = prompt("Introduceți descrierea ștergerii, sau apăsați OK pentru a accepta-o pe cea generată automat.", presetReason);
				} else {
					reason = presetReason;
				}
			}
			if (!reason || !reason.replace(/^\s*/, "").replace(/\s*$/, "")) {
				Morebits.status.error("Cererea motivului", "n-ați specificat niciun motiv. Renunț...");
				return;
			}

			// open talk page of first contributor
			if( params.openusertalk ) {
				thispage = new Morebits.wiki.page( mw.config.get('wgPageName') );  // a necessary evil, in order to clear incorrect Morebits.status.text
				thispage.setCallbackParameters( params );
				thispage.lookupCreator( Twinkle.speedy.callbacks.sysop.openUserTalkPage );
			}

			thispage.setEditSummary( reason + Twinkle.getPref('deletionSummaryAd') );
			thispage.deletePage();

			// delete talk page
			if (params.deleteTalkPage &&
			    params.normalized !== 'f8' &&
			    document.getElementById( 'ca-talk' ).className !== 'new') {
				var talkpage = new Morebits.wiki.page( Morebits.wikipedia.namespaces[ mw.config.get('wgNamespaceNumber') + 1 ] + ':' + mw.config.get('wgTitle'), "șterg pagină de discuție" );
				talkpage.setEditSummary('[[WP:CȘR#G8|G8]]: Pagină de discuție a unei pagini șterse [[' + mw.config.get('wgPageName') + "]]. " + Twinkle.getPref('deletionSummaryAd'));
				talkpage.deletePage();
			}

			// promote Unlink tool
			var $link, $bigtext;
			if( mw.config.get('wgNamespaceNumber') === 6 && params.normalized !== 'f8' ) {
				$link = $('<a/>', {
					'href': '#',
					'text': 'click here to go to the Unlink tool',
					'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
					'click': function(){
						Morebits.wiki.actionCompleted.redirect = null;
						Twinkle.speedy.dialog.close();
						Twinkle.unlink.callback("Elimin utilizări și linkuri spre fișier șters " + mw.config.get('wgPageName'));
					}
				});
				$bigtext = $('<span/>', {
					'text': 'Pentru a elimina utilizările paginii',
					'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
				});
				Morebits.status.info($bigtext[0], $link[0]);
			} else if (params.normalized !== 'f8') {
				$link = $('<a/>', {
					'href': '#',
					'text': 'faceți click aici pentru unealta de dezlegare',
					'css': { 'fontSize': '130%', 'fontWeight': 'bold' },
					'click': function(){
						Morebits.wiki.actionCompleted.redirect = null;
						Twinkle.speedy.dialog.close();
						Twinkle.unlink.callback("Elimin linkuri spre pagina ștearsă " + mw.config.get('wgPageName'));
					}
				});
				$bigtext = $('<span/>', {
					'text': 'Pentru a elimina utilizările paginii',
					'css': { 'fontSize': '130%', 'fontWeight': 'bold' }
				});
				Morebits.status.info($bigtext[0], $link[0]);
			}

			// delete redirects
			if (params.deleteRedirects) {
				var query = {
					'action': 'query',
					'list': 'backlinks',
					'blfilterredir': 'redirects',
					'bltitle': mw.config.get('wgPageName'),
					'bllimit': 5000  // 500 is max for normal users, 5000 for bots and sysops
				};
				var wikipedia_api = new Morebits.wiki.api( 'obțin lista de redirecționări...', query, Twinkle.speedy.callbacks.sysop.deleteRedirectsMain,
					new Morebits.status( 'ștergere redirecționări' ) );
				wikipedia_api.params = params;
				wikipedia_api.post();
			}
		},
		openUserTalkPage: function( pageobj ) {
			pageobj.getStatusElement().unlink();  // don't need it anymore
			var user = pageobj.getCreator();
			var statusIndicator = new Morebits.status('Deschid pagina de discuție a utilizatorului ' + user, 'opening...');

			var query = {
				'title': 'Discuție Utilizator:' + user,
				'action': 'edit',
				'preview': 'yes',
				'vanarticle': mw.config.get('wgPageName').replace(/_/g, ' ')
			};
			switch( Twinkle.getPref('userTalkPageMode') ) {
			case 'tab':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), '_tab' );
				break;
			case 'blank':
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1400,height=800' );
				break;
			case 'window':
				/* falls through */
				default :
				window.open( mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/index.php?' + Morebits.queryString.create( query ), 'twinklewarnwindow', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1400,height=800' );
				break;
			}

			statusIndicator.info( 'complete' );
		},
		deleteRedirectsMain: function( apiobj ) {
			var xmlDoc = apiobj.getXML();
			var $snapshot = $(xmlDoc).find('backlinks bl');

			var total = $snapshot.length;

			if( !total ) {
				return;
			}

			var statusIndicator = apiobj.statelem;
			statusIndicator.status("0%");

			var onsuccess = function( apiobj ) {
				var obj = apiobj.params.obj;
				var total = apiobj.params.total;
				var now = parseInt( 100 * ++(apiobj.params.current)/total, 10 ) + '%';
				obj.update( now );
				apiobj.statelem.unlink();
				if( apiobj.params.current >= total ) {
					obj.info( now + ' (completed)' );
					Morebits.wiki.removeCheckpoint();
				}
			};

			Morebits.wiki.addCheckpoint();

			var params = clone( apiobj.params );
			params.current = 0;
			params.total = total;
			params.obj = statusIndicator;

			$snapshot.each(function(key, value) {
				var title = $(value).attr('title');
				var page = new Morebits.wiki.page(title, 'șterg redirecționare "' + title + '"');
				page.setEditSummary('[[WP:CȘR#G8|G8]]: Redirecționare spre pagină ștearsă [[' + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('deletionSummaryAd'));
				page.deletePage(onsuccess);
			});
		}
	},





	user: {
		main: function(pageobj) {
			var statelem = pageobj.getStatusElement();

			if (!pageobj.exists()) {
				statelem.error( "Se pare că pagina nu există; poate că a fost deja ștearsă" );
				return;
			}

			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			statelem.status( 'Caut etichete pe pagină...' );

			// check for existing deletion tags
			var tag = /(?:\{\{\s*(șr|speedy|db-.*?)(?:\s*\||\s*\}\}))/.exec( text );
			if( tag ) {
				statelem.error( [ Morebits.htmlNode( 'strong', tag[1] ) , " deja există în pagină." ] );
				return;
			}

			var xfd = /(?:\{\{((\u0219|\u015F)terge|delete)[^{}]*?\}\})/i.exec( text );
			if( xfd && !confirm( "Formatul de ștergere {{" + xfd[1] + "}} a fost găsit în pagină. Doriți să mai propuneți pentru ștergere rapidă?" ) ) {
				return;
			}

			var code, parameters, i;
			if (params.normalized === 'multiple')
			{
				code = "{{db-multiple";
				for (i in Twinkle.speedy.dbmultipleCriteria) {
					if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string') {
						code += "|" + Twinkle.speedy.dbmultipleCriteria[i].toUpperCase();
					}
				}
				for (i in Twinkle.speedy.dbmultipleParameters) {
					if (typeof Twinkle.speedy.dbmultipleParameters[i] === 'string') {
						code += "|" + i + "=" + Twinkle.speedy.dbmultipleParameters[i];
					}
				}
				code += "}}";
				params.utparams = [];
			}
			else
			{
				parameters = Twinkle.speedy.getParameters(params.value, params.normalized, statelem);
				if (!parameters) {
					return;  // the user aborted
				}
				code = "{{șr-" + params.value;
				for (i in parameters) {
					if (typeof parameters[i] === 'string') {
						code += "|" + i + "=" + parameters[i];
					}
				}
				code += "}}";
				params.utparams = Twinkle.speedy.getUserTalkParameters(params.normalized, parameters);
			}

			var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
			// patrol the page, if reached from Special:NewPages
			if( Twinkle.getPref('markSpeedyPagesAsPatrolled') ) {
				thispage.patrol();
			}

			// Notification to first contributor
			if (params.usertalk) {
				var callback = function(pageobj) {
					var initialContrib = pageobj.getCreator();
					var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")");
					var notifytext;

					// specialcase "db" and "db-multiple"
					// XXX modify the "db-csd-notice-custom" template to cater for these special cases
					switch (params.normalized)
					{
						case 'db':
							notifytext = "\n\n{{subst:db-reason-notice|1=" + mw.config.get('wgPageName');
							break;
						case 'multiple':
							notifytext = "\n\n{{subst:db-notice-multiple|1=" + mw.config.get('wgPageName');
							break;
						default:
							notifytext = "\n\n{{subst:db-csd-notice-custom|1=" + mw.config.get('wgPageName') + "|2=" + params.value;
							break;
					}
					for (var i in params.utparams) {
						if (typeof params.utparams[i] === 'string') {
							notifytext += "|" + i + "=" + params.utparams[i];
						}
					}
					notifytext += (params.welcomeuser ? "" : "|nowelcome=yes") + "}} ~~~~";

					usertalkpage.setAppendText(notifytext);
					usertalkpage.setEditSummary("Notificare: propunere pentru ștergere rapidă a paginii [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
					usertalkpage.setCreateOption('recreate');
					usertalkpage.setFollowRedirect(true);
					usertalkpage.append();

					// add this nomination to the user's userspace log, if the user has enabled it
					if (params.lognomination) {
						Twinkle.speedy.callbacks.user.addToLog(params, initialContrib);
					}
				};
				thispage.lookupCreator(callback);
			}
			// or, if not notifying, add this nomination to the user's userspace log without the initial contributor's name
			else if (params.lognomination) {
				Twinkle.speedy.callbacks.user.addToLog(params, null);
			}

			// Wrap SD template in noinclude tags if we are in template space.
			// Won't work with userboxes in userspace, or any other transcluded page outside template space
			if (mw.config.get('wgNamespaceNumber') === 10) {  // Template:
				code = "<noinclude>" + code + "</noinclude>";
			}

			// Remove tags that become superfluous with this action
			text = text.replace(/\{\{\s*(New unreviewed article|Userspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, "");

			// Generate edit summary for edit
			var editsummary;
			switch (params.normalized)
			{
				case 'db':
					editsummary = 'Cer [[WP:CȘR|ștergere rapidă]] cu explicația \"' + parameters["1"] + '\".';
					break;
				case 'multiple':
					editsummary = 'Cer ștergere rapidă (';
					for (i in Twinkle.speedy.dbmultipleCriteria) {
						if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string') {
							editsummary += '[[WP:CȘR#' + Twinkle.speedy.dbmultipleCriteria[i].toUpperCase() + '|CȘR ' + Twinkle.speedy.dbmultipleCriteria[i].toUpperCase() + ']], ';
						}
					}
					editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
					editsummary += ').';
					break;
				case 'g6':
					if (params.value === 'histmerge') {
						editsummary = "Cer unirea istoricului cu [[" + parameters["1"] + "]] ([[WP:CȘR#G6|CSD G6]]).";
						break;
					}
					/* falls through */
				default:
					editsummary = "Cer ștergerea rapidă ([[WP:CȘR#" + params.normalized.toUpperCase() + "|CȘR " + params.normalized.toUpperCase() + "]]).";
					break;
			}

			pageobj.setPageText(code + ((params.normalized === 'g10' || Twinkle.speedy.dbmultipleCriteria.indexOf('g10') !== -1) ?
					'' : ("\n" + text) )); // cause attack pages to be blanked
			pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
			pageobj.setWatchlist(params.watch);
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		},

		// note: this code is also invoked from twinkleimage
		// the params used are:
		//   for all: params.normalized
		//   for CSD: params.value
		//   for DI: params.fromDI = true, params.type
		addToLog: function(params, initialContrib) {
			var wikipedia_page = new Morebits.wiki.page("Utilizator:" + mw.config.get('wgUserName') + "/" + Twinkle.getPref('speedyLogPageName'), "Adaug jurnal al cererilor efectuate");
			params.logInitialContrib = initialContrib;
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.speedy.callbacks.user.saveLog);
		},

		saveLog: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			// add blurb if log page doesn't exist
			if (!pageobj.exists()) {
				text =
					"Acesta este un jurnal al tuturor [[WP:CȘR|ștergerilor rapide]] cerute de acest utilizator folosind modulul [[WP:TW|Twinkle]] CSD.\n\n" +
					"Dacă nu doriți ținerea acestui jurnal, dezactivați opțiunea la [[Wikipedia:Twinkle/Preferences|preferințe]], și " +
					"cereți ștergerea acestei pagini conform [[WP:CȘR#U1|CȘR U1]].\n";
				if (Morebits.userIsInGroup("sysop")) {
					text += "\nAcest jurnal nu înregistrează ștergerile directe folosind Twinkle.\n";
				}
			}

			// create monthly header
			var date = new Date();
			var headerRe = new RegExp("^==+\\s*" + date.getUTCMonthName() + "\\s+" + date.getUTCFullYear() + "\\s*==+", "m");
			if (!headerRe.exec(text)) {
				text += "\n\n=== " + date.getUTCMonthName() + " " + date.getUTCFullYear() + " ===";
			}

			text += "\n# [[:" + mw.config.get('wgPageName') + "]]: ";
			if (params.fromDI) {
				text += "DI [[WP:CSD#" + params.normalized.toUpperCase() + "|CSD " + params.normalized.toUpperCase() + "]] (" + params.type + ")";
			} else {
				switch (params.normalized)
				{
					case 'db':
						text += "{{tl|șr}}";
						break;
					case 'multiple':
						text += "criterii multiple (";
						for (var i in Twinkle.speedy.dbmultipleCriteria) {
							if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string') {
								text += '[[WP:CȘR#' + Twinkle.speedy.dbmultipleCriteria[i].toUpperCase() + '|' + Twinkle.speedy.dbmultipleCriteria[i].toUpperCase() + ']], ';
							}
						}
						text = text.substr(0, text.length - 2);  // remove trailing comma
						text += ')';
						break;
					default:
						text += "[[WP:CȘR#" + params.normalized.toUpperCase() + "|CȘR " + params.normalized.toUpperCase() + "]] ({{tl|șr-" + params.value + "}})";
						break;
				}
			}

			if (params.logInitialContrib) {
				text += "; notified {{user|" + params.logInitialContrib + "}}";
			}
			text += " ~~~~~\n";

			pageobj.setPageText(text);
			pageobj.setEditSummary("Înregistrez în jurnal propunerea pentru ștergere rapidă a paginii [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			pageobj.setCreateOption("recreate");
			pageobj.save();
		}
	}
};

// prompts user for parameters to be passed into the speedy deletion tag
Twinkle.speedy.getParameters = function twinklespeedyGetParameters(value, normalized, statelem)
{
	var parameters = [];
	switch( normalized ) {
		case 'db':
			var dbrationale = prompt('Introduceți o explicație.   \n\"Pagina trebuie ștearsă deoarece:\"', "");
			if (!dbrationale || !dbrationale.replace(/^\s*/, "").replace(/\s*$/, ""))
			{
				statelem.error( 'You must specify a rationale.  Aborted by user.' );
				return null;
			}
			parameters["1"] = dbrationale;
			break;
		case 'u1':
			if (mw.config.get('wgNamespaceNumber') === 3 && !((/\//).test(mw.config.get('wgTitle'))))
			{
				var u1rationale = prompt('Introduceți o justificare pentru ștergerea acestei pagini de discuții:', "");
				if (!u1rationale || !u1rationale.replace(/^\s*/, "").replace(/\s*$/, ""))
				{
					statelem.error( 'Trebuie să specificați o justificare. Acțiune anulată.' );
					return null;
				}
				parameters.rationale = u1rationale;
			}
			break;
		case 'f8':
			var pagenamespaces = mw.config.get('wgPageName').replace( '_', ' ' );
			var filename = prompt( 'Introduceți numele fișierului de la Commons:', pagenamespaces );
			if (filename === null)
			{
				statelem.error( 'Acțiune anulată.' );
				return null;
			}
			if (filename !== '' && filename !== pagenamespaces)
			{
				if (filename.indexOf("Image:") === 0 || filename.indexOf("File:") === 0 || filename.indexOf("Imagine:") === 0 || filename.indexOf("Fișier:") === 0)
				{
					parameters["1"] = filename;
				}
				else
				{
					statelem.error("Din numele fișierului lipsește prefixul File:. Acțiune anulată.");
					return null;
				}
			}
			parameters.date = "~~~~~";
			break;
		case 'g6':
			switch( value ) {
				case 'histmerge':
					var mergetitle = prompt( 'Introduceți titlul cu care să uniți:', "" );
					if (mergetitle === null)
					{
						statelem.error( 'Acțiune anulată.' );
						return null;
					}
					parameters["1"] = mergetitle;
					break;
				case 'move':
					var title = prompt( 'Introduceți titlul paginii de mutat aici:', "" );
					if (title === null)
					{
						statelem.error( 'Acțiune anulată.' );
						return null;
					}
					var reason = prompt( 'Introduceți motivul mutării:', "" );
					if (reason === null)
					{
						statelem.error( 'Acțiune anulată.' );
						return null;
					}
					parameters["1"] = title;
					parameters["2"] = reason;
					break;
				case 'copypaste':
					var copytitle = prompt( 'Introduceți titlul paginii din care s-a copiat textul:', "" );
					if (copytitle === null)
					{
						statelem.error( 'Acțiune anulată.' );
						return null;
					}
					parameters["1"] = copytitle;
					break;
				case 'g6':
					var g6rationale = prompt( 'Introduceți o justificare (lăsați gol pentru a sări):', "" );
					if (g6rationale === null)
					{
						statelem.error( 'Acțiune anulată.' );
						return null;
					}
					if (g6rationale !== '')
					{
						parameters.rationale = g6rationale;
					}
					break;
				default:
					break;
			}
			break;
		case 'g7':
			if (Twinkle.getPref('speedyPromptOnG7'))
			{
				var g7rationale = prompt('Introduceți un motiv (eventual un link unde userul a cerut ștergerea):', "");
				if (g7rationale === null)
				{
					statelem.error( 'Acțiune anulată.' );
					return null;
				}
				if (g7rationale !== '')
				{
					parameters.rationale = g7rationale;
				}
			}
			break;
		case 'f9':
		case 'g12':
			var url = prompt( 'Introduceți URL-ul dacă e disponibil, inclusiv "http://":', "" );
			if (url === null)
			{
				statelem.error( 'Acțiune anulată.' );
				return null;
			}
			parameters.url = url;
			break;
		case 'a2':
			var source = prompt('Introduceți un link interwiki spre articolul în altă limbă (de exemplu, "fr:Bonjour"):', "");
			if (source === null)
			{
				statelem.error('Acțiune anulată.');
				return null;
			}
			parameters.source = source;
			break;
		case 'a10':
			var duptitle = prompt( 'Introduceți titlul articolului duplicat:', "" );
			if (duptitle === null)
			{
				statelem.error( 'Acțiune anulată.' );
				return null;
			}
			parameters.article = duptitle;
			break;
		case 'f1':
			var img = prompt( 'Introduceți celălalt fișier, fără prefixul "Fișier:" sau "File:":', "" );
			if (img === null)
			{
				statelem.error( 'Acțiune anulată.' );
				return null;
			}
			parameters.filename = img;
			break;
		case 't3':
			var template = prompt( 'Introduceți formatul care îl înlocuiește pe acesta, fără prefixul "Format:"', "" );
			if (template === null)
			{
				statelem.error( 'Acțiune anulată.' );
				return null;
			}
			parameters["1"] = "~~~~~";
			parameters["2"] = template;
			break;
		case 'g10':
			parameters.blanked = 'yes';
			// it is actually blanked elsewhere in code, but setting the flag here
			break;
		case 'p1':
			var criterion = prompt( 'Introduceți codul criteriului de ștergere rapidă:   \n\n(A1 = fără context, A3 = fără conținut, A7 = nenotabil, A10 = duplicat)', "" );
			if (!criterion || !criterion.replace(/^\s*/, "").replace(/\s*$/, ""))
			{
				statelem.error( 'Criteriul este obligatoriu. Acțiune anulată.' );
				return null;
			}
			parameters["1"] = criterion;
			break;
		default:
			break;
	}
	return parameters;
};

// function for processing talk page notification template parameters
Twinkle.speedy.getUserTalkParameters = function twinklespeedyGetUserTalkParameters(normalized, parameters)
{
	var utparams = [];
	switch (normalized)
	{
		case 'db':
			utparams["2"] = parameters["1"];
			break;
		case 'a10':
			utparams.key1 = "article";
			utparams.value1 = parameters.article;
			break;
		default:
			break;
	}
	return utparams;
};

Twinkle.speedy.callback.evaluateSysop = function twinklespeedyCallbackEvaluateSysop(e)
{
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' ')); // for queen/king/whatever and country!

	var tag_only = e.target.form.tag_only;
	if( tag_only && tag_only.checked ) {
		Twinkle.speedy.callback.evaluateUser(e);
		return;
	}

	var value = e.target.values;
	var normalized = Twinkle.speedy.normalizeHash[ value ];

	var params = {
		value: value,
		normalized: normalized,
		watch: Twinkle.getPref('watchSpeedyPages').indexOf( normalized ) !== -1,
		reason: Twinkle.speedy.reasonHash[ value ],
		openusertalk: Twinkle.getPref('openUserTalkPageOnSpeedyDelete').indexOf( normalized ) !== -1,
		deleteTalkPage: e.target.form.talkpage && e.target.form.talkpage.checked,
		deleteRedirects: e.target.form.redirects.checked
	};
	Morebits.status.init( e.target.form );

	Twinkle.speedy.callbacks.sysop.main( params );
};

Twinkle.speedy.callback.evaluateUser = function twinklespeedyCallbackEvaluateUser(e) {
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!
	var value = e.target.values;

	if (value === 'multiple')
	{
		e.target.form.style.display = "none"; // give the user a cue that the dialog is being changed
		setTimeout(function() {
			Twinkle.speedy.initDialog(Twinkle.speedy.callback.doMultiple, false, e.target.form.parentNode);
		}, 150);
		return;
	}

	if (value === 'multiple-finish') {
		value = 'multiple';
	}
	else
	{
		// clear these out, whatever the case, to avoid errors
		Twinkle.speedy.dbmultipleCriteria = [];
		Twinkle.speedy.dbmultipleParameters = [];
	}

	var normalized = Twinkle.speedy.normalizeHash[ value ];

	// for sysops only
	if (['f4', 'f5', 'f6', 'f11'].indexOf(normalized) !== -1) {
		alert("Etichetarea cu F4, F5, F6 și F11 nu se poate face cu modulul CSD. Utilizați Imagine, sau deifați \"Tag page only\" dacă doreați să efectuați ștergerea.");
		return;
	}

	var i;

	// analyse each db-multiple criterion to determine whether to watch the page/notify the creator
	var watchPage = false;
	if (value === 'multiple')
	{
		for (i in Twinkle.speedy.dbmultipleCriteria)
		{
			if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string' &&
				Twinkle.getPref('watchSpeedyPages').indexOf(Twinkle.speedy.dbmultipleCriteria[i]) !== -1)
			{
				watchPage = true;
				break;
			}
		}
	}
	else
	{
		watchPage = Twinkle.getPref('watchSpeedyPages').indexOf(normalized) !== -1;
	}

	var notifyuser = false;
	if (value === 'multiple')
	{
		for (i in Twinkle.speedy.dbmultipleCriteria)
		{
			if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string' &&
				Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(Twinkle.speedy.dbmultipleCriteria[i]) !== -1)
			{
				notifyuser = true;
				break;
			}
		}
	}
	else
	{
		notifyuser = (Twinkle.getPref('notifyUserOnSpeedyDeletionNomination').indexOf(normalized) !== -1) && e.target.form.notify.checked;
	}

	var welcomeuser = false;
	if (notifyuser)
	{
		if (value === 'multiple')
		{
			for (i in Twinkle.speedy.dbmultipleCriteria)
			{
				if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string' &&
					Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(Twinkle.speedy.dbmultipleCriteria[i]) !== -1)
				{
					welcomeuser = true;
					break;
				}
			}
		}
		else
		{
			welcomeuser = Twinkle.getPref('welcomeUserOnSpeedyDeletionNotification').indexOf(normalized) !== -1;
		}
	}

	var csdlog = false;
	if (Twinkle.getPref('logSpeedyNominations') && value === 'multiple')
	{
		for (i in Twinkle.speedy.dbmultipleCriteria)
		{
			if (typeof Twinkle.speedy.dbmultipleCriteria[i] === 'string' &&
				Twinkle.getPref('noLogOnSpeedyNomination').indexOf(Twinkle.speedy.dbmultipleCriteria[i]) === -1)
			{
				csdlog = true;
				break;
			}
		}
	}
	else
	{
		csdlog = Twinkle.getPref('logSpeedyNominations') && Twinkle.getPref('noLogOnSpeedyNomination').indexOf(normalized) === -1;
	}

	var params = {
		value: value,
		normalized: normalized,
		watch: watchPage,
		usertalk: notifyuser,
		welcomeuser: welcomeuser,
		lognomination: csdlog
	};

	Morebits.status.init( e.target.form );

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Tagging complete";

	var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Tagging page");
	wikipedia_page.setCallbackParameters(params);
	wikipedia_page.load(Twinkle.speedy.callbacks.user.main);
};

Twinkle.speedy.dbmultipleCriteria = [];
Twinkle.speedy.dbmultipleParameters = [];
Twinkle.speedy.callback.doMultiple = function twinklespeedyCallbackDoMultiple(e)
{
	var value = e.target.values;
	var normalized = Twinkle.speedy.normalizeHash[value];
	if (value !== 'multiple-finish')
	{
		if (Twinkle.speedy.dbmultipleCriteria.indexOf(normalized) !== -1)
		{
			alert('You already selected that criterion. Please choose another.');
		}
		else
		{
			var parameters = Twinkle.speedy.getParameters(value, normalized, Morebits.status);
			if (parameters)
			{
				for (var i in parameters) {
					if (typeof parameters[i] === 'string') {
						Twinkle.speedy.dbmultipleParameters[i] = parameters[i];
					}
				}
				Twinkle.speedy.dbmultipleCriteria.push(normalized);
			}
		}
		e.target.form.style.display = "none"; // give the user a cue that the dialog is being changed
		setTimeout(function() {
			Twinkle.speedy.initDialog(Twinkle.speedy.callback.doMultiple, false, e.target.form.parentNode);
		}, 150);
	}
	else
	{
		Twinkle.speedy.callback.evaluateUser(e);
	}
};

/*
 ****************************************
 *** twinkleunlink.js: Unlink module
 ****************************************
 * Mode of invocation:     Tab ("Unlink")
 * Active on:              Non-special pages
 * Config directives in:   TwinkleConfig
 */

Twinkle.unlink = function twinkleunlink() {
	if( mw.config.get('wgNamespaceNumber') < 0 ) {
		return;
	}
	twAddPortletLink(function(){Twinkle.unlink.callback()}, "Dezleagă", "tw-unlink", "Dezleagă legăturile către aici"); //wrap call in function, callback expects a reason parameter.
};

Twinkle.unlink.getChecked2 = function twinkleunlinkGetChecked2( nodelist ) {
	if( !( nodelist instanceof NodeList ) && !( nodelist instanceof HTMLCollection ) ) {
		return nodelist.checked ? [ nodelist.value ] : [];
	}
	var result = [];
	for(var i  = 0; i < nodelist.length; ++i ) {
		if( nodelist[i].checked ) {
			result.push( nodelist[i].value );
		}
	}
	return result;
};

// the parameter is used when invoking unlink from admin speedy
Twinkle.unlink.callback = function(presetReason) {
	var Window = new Morebits.simpleWindow( 800, 400 );
	Window.setTitle( "Elimină legături" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#unlink" );

	var form = new Morebits.quickForm( Twinkle.unlink.callback.evaluate );
	form.append( {
		type: 'textarea',
		name: 'reason',
		label: 'Motiv: ',
		value: (presetReason ? presetReason : '')
	} );

	var query;
	if(mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").IMAGE) {
		query = {
			'action': 'query',
			'list': [ 'backlinks', 'imageusage' ],
			'bltitle': mw.config.get('wgPageName'),
			'iutitle': mw.config.get('wgPageName'),
			'bllimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500, // 500 is max for normal users, 5000 for bots and sysops
			'iulimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500, // 500 is max for normal users, 5000 for bots and sysops
			'blnamespace': Twinkle.getPref('unlinkNamespaces') // Main namespace and portal namespace only, keep on talk pages.
		};
	} else {
		query = {
			'action': 'query',
			'list': 'backlinks',
			'bltitle': mw.config.get('wgPageName'),
			'blfilterredir': 'nonredirects',
			'bllimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500, // 500 is max for normal users, 5000 for bots and sysops
			'blnamespace': Twinkle.getPref('unlinkNamespaces') // Main namespace and portal namespace only, keep on talk pages.
		};
	}
	var wikipedia_api = new Morebits.wiki.api( 'Aduc legături', query, Twinkle.unlink.callbacks.display.backlinks );
	wikipedia_api.params = { form: form, Window: Window, image: mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").IMAGE };
	wikipedia_api.post();

	var root = document.createElement( 'div' );
	root.style.padding = '15px';  // just so it doesn't look broken
	Morebits.status.init( root );
	wikipedia_api.statelem.status( "încărcare..." );
	Window.setContent( root );
	Window.display();
};

Twinkle.unlink.callback.evaluate = function twinkleunlinkCallbackEvaluate(event) {
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!

	Twinkle.unlink.backlinksdone = 0;
	Twinkle.unlink.imageusagedone = 0;

	function processunlink(pages, imageusage) {
		var statusIndicator = new Morebits.status((imageusage ? 'Dezleg instanțele de utilizare a fișierului' : 'Elimin legăturile'), '0%');
		var total = pages.length;  // removing doubling of this number - no apparent reason for it

		Morebits.wiki.addCheckpoint();

		if( !pages.length ) {
			statusIndicator.info( '100% (terminat)' );
			Morebits.wiki.removeCheckpoint();
			return;
		}

		// get an edit token
		var params = { reason: reason, imageusage: imageusage, globalstatus: statusIndicator, current: 0, total: total };
		for (var i = 0; i < pages.length; ++i)
		{
			var myparams = clone(params);
			var articlepage = new Morebits.wiki.page(pages[i], 'Dezleg în articolul "' + pages[i] + '"');
			articlepage.setCallbackParameters(myparams);
			articlepage.load(imageusage ? Twinkle.unlink.callbacks.unlinkImageInstances : Twinkle.unlink.callbacks.unlinkBacklinks);
		}
	}

	var reason = event.target.reason.value;
	var backlinks, imageusage;
	if( event.target.backlinks ) {
		backlinks = Twinkle.unlink.getChecked2(event.target.backlinks);
	}
	if( event.target.imageusage ) {
		imageusage = Twinkle.unlink.getChecked2(event.target.imageusage);
	}

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( event.target );
	Morebits.wiki.addCheckpoint();
	if (backlinks) {
		processunlink(backlinks, false);
	}
	if (imageusage) {
		processunlink(imageusage, true);
	}
	Morebits.wiki.removeCheckpoint();
};

Twinkle.unlink.backlinksdone = 0;
Twinkle.unlink.imageusagedone = 0;

Twinkle.unlink.callbacks = {
	display: {
		backlinks: function twinkleunlinkCallbackDisplayBacklinks(apiobj) {
			var xmlDoc = apiobj.responseXML;
			var havecontent = false;
			var list, namespaces, i;

			if( apiobj.params.image ) {
				var imageusage = $(xmlDoc).find('query imageusage iu');
				list = [];
				for ( i = 0; i < imageusage.length; ++i ) {
					var usagetitle = imageusage[i].getAttribute('title');
					list.push( { label: usagetitle, value: usagetitle, checked: true } );
				}
				if (!list.length)
				{
					apiobj.params.form.append( { type: 'div', label: 'Nu s-au găsit utilizări ale fișierului.' } );
				}
				else
				{
					apiobj.params.form.append( { type:'header', label: 'Utilizarea fișierului' } );
					namespaces = [];
					$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
						namespaces.push(Morebits.wikipedia.namespacesFriendly[v]);
					});
					apiobj.params.form.append( {
						type: 'div',
						label: "Spații de nume selectate: " + namespaces.join(', '),
						tooltip: "Puteți modifica aceasta din preferințele Twinkle"
					});
					if ($(xmlDoc).find('query-continue').length) {
						apiobj.params.form.append( {
							type: 'div',
							label: "Primele " + list.length.toString() + " utilizări."
						});
					}
					apiobj.params.form.append( {
						type: 'checkbox',
						name: 'imageusage',
						list: list
					} );
					havecontent = true;
				}
			}

			var backlinks = $(xmlDoc).find('query backlinks bl');
			if( backlinks.length > 0 ) {
				list = [];
				for ( i = 0; i < backlinks.length; ++i ) {
					var title = backlinks[i].getAttribute('title');
					list.push( { label: title, value: title, checked: true } );
				}
				apiobj.params.form.append( { type:'header', label: 'Backlinks' } );
				namespaces = [];
				$.each(Twinkle.getPref('unlinkNamespaces'), function(k, v) {
					namespaces.push(Morebits.wikipedia.namespacesFriendly[v]);
				});
				apiobj.params.form.append( {
					type: 'div',
					label: "Spații de nume selectate: " + namespaces.join(', '),
					tooltip: "Puteți modifica aceasta din preferințele Twinkle"
				});
				if ($(xmlDoc).find('query-continue').length) {
					apiobj.params.form.append( {
						type: 'div',
						label: "Primele " + list.length.toString() + " legături."
					});
				}
				apiobj.params.form.append( {
					type: 'checkbox',
					name: 'backlinks',
					list: list
				});
				havecontent = true;
			}
			else
			{
				apiobj.params.form.append( { type: 'div', label: 'No backlinks found.' } );
			}

			if (havecontent) {
				apiobj.params.form.append( { type:'submit' } );
			}

			var result = apiobj.params.form.render();
			apiobj.params.Window.setContent( result );
		}
	},
	unlinkBacklinks: function twinkleunlinkCallbackUnlinkBacklinks(pageobj) {
		var text, oldtext;
		text = oldtext = pageobj.getPageText();
		var params = pageobj.getCallbackParameters();

		var wikiPage = new Mediawiki.Page(text);
		wikiPage.removeLink(mw.config.get('wgPageName'));
		text = wikiPage.getText();
		if (text === oldtext) {
			// Nothing to do, return
			Twinkle.unlink.callbacks.success(pageobj);
			Morebits.wiki.actionCompleted();
			return;
		}

		pageobj.setPageText(text);
		pageobj.setEditSummary("Elimin legăturile către \"" + mw.config.get('wgPageName') + "\": " + params.reason + "." + Twinkle.getPref('summaryAd'));
		pageobj.setCreateOption('nocreate');
		pageobj.save(Twinkle.unlink.callbacks.success);
	},
	unlinkImageInstances: function twinkleunlinkCallbackUnlinkImageInstances(pageobj) {
		var text, oldtext;
		text = oldtext = pageobj.getPageText();
		var params = pageobj.getCallbackParameters();

		var wikiPage = new Mediawiki.Page(text);
		wikiPage.commentOutImage(mw.config.get('wgTitle'), 'Comentat');
		text = wikiPage.getText();
		if (text === oldtext) {
			// Nothing to do, return
			Twinkle.unlink.callbacks.success(pageobj);
			Morebits.wiki.actionCompleted();
			return;
		}

		pageobj.setPageText(text);
		pageobj.setEditSummary("Comentez utilizarea fișierului \"" + mw.config.get('wgPageName') + "\": " + params.reason + "." + Twinkle.getPref('summaryAd'));
		pageobj.setCreateOption('nocreate');
		pageobj.save(Twinkle.unlink.callbacks.success);
	},
	success: function twinkleunlinkCallbackSuccess(pageobj) {
		var statelem = pageobj.getStatusElement();
		statelem.info('gata');

		var params = pageobj.getCallbackParameters();
		var total = params.total;
		var now = parseInt( 100 * (params.imageusage ? ++(Twinkle.unlink.imageusagedone) : ++(Twinkle.unlink.backlinksdone))/total, 10 ) + '%';
		params.globalMorebits.status.update( now );
		if((params.imageusage ? Twinkle.unlink.imageusagedone : Twinkle.unlink.backlinksdone) >= total) {
			params.globalMorebits.status.info( now + ' (terminat)' );
			Morebits.wiki.removeCheckpoint();
		}
	}
};

/*
 ****************************************
 *** twinklewarn.js: Warn module
 ****************************************
 * Mode of invocation:     Tab ("Warn")
 * Active on:              User talk pages
 * Config directives in:   TwinkleConfig
 */

Twinkle.warn = function twinklewarn() {
	if( mw.config.get('wgNamespaceNumber') === 3 ) {
		if(twinkleUserAuthorized) {
			twAddPortletLink(Twinkle.warn.callback, "Avertizează", "tw-warn", "Avertizează/anunță utilizatorul");
		} else {
			twAddPortletLink(function() {
				alert("Aveți cont prea recent pentru a utiliza Twinkle.");
			}, "Avertizează", "tw-warn", "Avertizează/anunță utilizatorul", "");
		}
	}
};

Twinkle.warn.callback = function twinklewarnCallback() {
	var Window = new Morebits.simpleWindow( 600, 440 );
	Window.setTitle( "Warn/notify user" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Alegerea nivelului de avertizare", "WP:UWUL#Levels" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#warn" );

	var form = new Morebits.quickForm( Twinkle.warn.callback.evaluate );
	var main_select = form.append( {
			type:'field',
			label:'Alegeți tipul de avertisment',
			tooltip:'First choose a main warning group, then the specific warning to issue.'
		} );

	var main_group = main_select.append( {
			type:'select',
			name:'main_group',
			event:Twinkle.warn.callback.change_category
		} );

	var defaultGroup = parseInt(Twinkle.getPref('defaultWarningGroup'), 10);
	main_group.append( { type:'option', label:'Notă generală (1)', value:'level1', selected: ( defaultGroup === 1 || defaultGroup < 1 || ( Morebits.userIsInGroup( 'sysop' ) ? defaultGroup > 8 : defaultGroup > 7 ) ) } );
	main_group.append( { type:'option', label:'Atenționare (2)', value:'level2', selected: ( defaultGroup === 2 ) } );
	main_group.append( { type:'option', label:'Avertisment (3)', value:'level3', selected: ( defaultGroup === 3 ) } );
	main_group.append( { type:'option', label:'Ultim avertisment (4)', value:'level4', selected: ( defaultGroup === 4 ) } );
	main_group.append( { type:'option', label:'Unic avertisment (4im)', value:'level4im', selected: ( defaultGroup === 5 ) } );
	main_group.append( { type:'option', label:'Notificări simple', value:'singlenotice', selected: ( defaultGroup === 6 ) } );
	main_group.append( { type:'option', label:'Avertismente simple', value:'singlewarn', selected: ( defaultGroup === 7 ) } );
	if( Morebits.userIsInGroup( 'sysop' ) ) {
		main_group.append( { type:'option', label:'Blocare', value:'block', selected: ( defaultGroup === 8 ) } );
	}

	main_select.append( { type:'select', name:'sub_group', event:Twinkle.warn.callback.change_subcategory } ); //Will be empty to begin with.

	form.append( {
			type:'input',
			name:'article',
			label:'Articol legat',
			value:( Morebits.queryString.exists( 'vanarticle' ) ? Morebits.queryString.get( 'vanarticle' ) : '' ),
			tooltip:'An article can be linked within the notice, perhaps because it was a revert to said article that dispatched this notice. Leave empty for no article to be linked.'
		} );

	var more = form.append( { type:'field', label:'Completați (opțional) un motiv și apăsați \"Submit\"' } );
	more.append( { type:'textarea', label:'More:', name:'reason', tooltip:'Perhaps a reason, or that a more detailed notice must be appended' } );

	var previewlink = document.createElement( 'a' );
	$(previewlink).click(function(){
		Twinkle.warn.callbacks.preview();
	});
	previewlink.style.cursor = "pointer";
	previewlink.textContent = 'Previzualizare';
	more.append( { type: 'div', name: 'warningpreview', label: [ previewlink ] } );

	more.append( { type:'submit', label:'Submit' } );

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

	// We must init the first choice (General Note);
	var evt = document.createEvent( "Event" );
	evt.initEvent( 'change', true, true );
	result.main_group.dispatchEvent( evt );
};

// This is all the messages that might be dispatched by the code
// Each of the individual templates require the following information:
//   label (required): A short description displayed in the dialog
//   summary (required): The edit summary used. If an article name is entered, the summary is postfixed with "on [[article]]", and it is always postfixed with ". $summaryAd"
//   suppressArticleInSummary (optional): Set to true to suppress showing the article name in the edit summary. Useful if the warning relates to attack pages, or some such.
Twinkle.warn.messages = {
		level1: {
		"au-vandalism1": {
			label:"Vandalism",
			summary:"Notă generală: Modificare neconstructivă"
		},
		"au-eroare1": {
			label:"Erori",
			summary:"Notă generală: Modificări eronate"
		},
		"au-test1": {
			label:"Modificări de test", 
			summary:"Notă generală: Modificări de test" 
		},
		"au-ștergeri1": { 
			label:"Ștergerea conținutului paginilor", 
			summary:"Notă generală: Ștergerea conținutului paginilor" 
		},
		"au-tdel1": { 
			label:"Ștergerea formatelor de întreținere", 
			summary:"Notă generală: Ștergerea formatelor de întreținere" 
		},
		"au-glumă1": { 
			label:"Glume nepotrivite", 
			summary:"Notă generală: Glume nepotrivite" 
		},
		"au-pg-nouă1": { 
			label:"Crearea unor pagini nepotrivite", 
			summary:"Notă generală: Crearea unor pagini nepotrivite" 
		},
		"au-spam1": { 
			label:"Adăugarea unor legături spam", 
			summary:"Notă generală: Adăugarea unor legături spam" 
		},
		"au-reclamă1": { 
			label:"Adăugarea de reclame", 
			summary:"Notă generală: Adăugarea de reclame" 
		},
		"au-surse1": { 
			label:"Adăugarea unor materiale fără sursă și fără note de subsol", 
			summary:"Notă generală: Adăugarea unor materiale fără sursă și fără note de subsol" 
		},
		"au-biog1": { 
			label:"Adăugarea unor informații controversate fără note despre personalități în viață", 
			summary:"Notă generală: Afirmații controversate fără note despre personalități în viață" 
		},
		"au-mos1": { 
			label:"Manualul de stil", 
			summary:"Notă generală: Formatare, dată, limbă, etc. (Manualul de stil)" 
		},
		"au-afd1": { 
			label:"Ștergerea formatului \{\{Șterge\}\}", 
			summary:"Notă generală: Ștergerea formatului \{\{Șterge\}\}" 
		},
		"au-pdvn1": { 
			label:"Lipsă de neutralitate", 
			summary:"Notă generală: Lipsă de neutralitate" 
		},
		"au-trad1": { 
			label:"Traducere automată", 
			summary:"Notă generală: Traduceri automate" 
		},
		"au-vpd1": { 
			label:"Modificare mesajelor altora în paginile de discuții", 
			summary:"Notă generală: Modificare mesajelor altora în paginile de discuții" 
		},
		"au-discuții1": { 
			label:"Utilizarea Wikipediei ca pe un forum", 
			summary:"Notă generală: Utilizarea Wikipediei ca pe un forum" 
		},
		"au-plătit1": {
			label:"Contribuții plătite",
			summary:"Notă generală: Vă rog să declarați contribuțiile plătite"
		},
	},
	level2: {
		"au-vandalism2": { 
			label:"Vandalism", 
			summary:"Atenționare: Vandalism" 
		},
		"au-eroare2": {
			label:"Eroare",
			summary:"Atenționare: Informații false"
		},
		"au-test2": { 
			label:"Modificări de test", 
			summary:"Atenționare: Modificări de test" 
		},
		"au-ștergeri2": { 
			label:"Ștergerea conținutului paginilor", 
			summary:"Atenționare: Ștergerea conținutului paginilor" 
		},
		"au-tdel2": { 
			label:"Ștergerea formatelor de întreținere", 
			summary:"Atenționare: Ștergerea formatelor de întreținere" 
		},
		"au-glumă2": { 
			label:"Glume nepotrivite", 
			summary:"Atenționare: Glume nepotrivite" 
		},
		"au-pg-nouă2": { 
			label:"Crearea unor pagini nepotrivite", 
			summary:"Atenționare: Crearea unor pagini nepotrivite" 
		},
		"au-spam2": { 
			label:"Adăugarea unor legături spam", 
			summary:"Atenționare: Adăugarea unor legături spam" 
		},
		"au-reclamă2": { 
			label:"Adăugarea de reclame", 
			summary:"Atenționare: Adăugarea de reclame" 
		},
		"au-surse2": { 
			label:"Adăugarea unor materiale fără sursă și fără note de subsol", 
			summary:"Atenționare: Adăugarea unor materiale fără sursă și fără note de subsol" 
		},
		"au-biog2": { 
			label:"Adăugarea unor informații controversate fără note despre personalități în viață", 
			summary:"Atenționare: Afirmații controversate fără note despre personalități în viață" 
		},
		"au-mos2": { 
			label:"Manualul de stil", 
			summary:"Atenționare: Formatare, dată, limbă, etc. (Manualul de stil)" 
		},
		"au-afd2": { 
			label:"Ștergerea formatului \{\{Șterge\}\}", 
			summary:"Atenționare: Ștergerea formatului \{\{Șterge\}\}" 
		},
		"au-pdvn2": { 
			label:"Lipsă de neutralitate", 
			summary:"Atenționare: Lipsă de neutralitate" 
		},
		"au-trad2": { 
			label:"Traducere automată", 
			summary:"Atenționare: Traduceri automate" 
		},
		"au-vpd2": { 
			label:"Modificare mesajelor altora în paginile de discuții", 
			summary:"Atenționare: Modificare mesajelor altora în paginile de discuții" 
		},
		"au-discuții2": { 
			label:"Utilizarea Wikipediei ca pe un forum", 
			summary:"Atenționare: Utilizarea Wikipediei ca pe un forum" 
		},
		"au-plătit2": {
			label:"Contribuții plătite",
			summary:"Atenționare: Contribuțiile plătite trebuie declarate"
		},
	},
	level3: {
		"au-vandalism3": { 
			label:"Vandalism", 
			summary:"Avertizare: Vandalism" 
		},
		"au-eroare3": {
			label:"Eroare",
			summary:"Avertizare: Informații false"
		},
		"au-test3": { 
			label:"Modificări de test", 
			summary:"Avertizare: Modificări de test" 
		},
		"au-ștergeri3": { 
			label:"Ștergerea conținutului paginilor", 
			summary:"Avertizare: Ștergerea conținutului paginilor" 
		},
		"au-tdel3": { 
			label:"Ștergerea formatelor de întreținere", 
			summary:"Avertizare: Ștergerea formatelor de întreținere" 
		},
		"au-glumă3": { 
			label:"Glume nepotrivite", 
			summary:"Avertizare: Glume nepotrivite" 
		},
		"au-pg-nouă3": { 
			label:"Crearea unor pagini nepotrivite", 
			summary:"Avertizare: Crearea unor pagini nepotrivite" 
		},
		"au-spam3": { 
			label:"Adăugarea unor legături spam", 
			summary:"Avertizare: Adăugarea unor legături spam" 
		},
		"au-reclamă3": { 
			label:"Adăugarea de reclame", 
			summary:"Avertizare: Adăugarea de reclame" 
		},
		"au-surse3": { 
			label:"Adăugarea unor materiale fără sursă și fără note de subsol", 
			summary:"Avertizare: Adăugarea unor materiale fără sursă și fără note de subsol" 
		},
		"au-biog3": { 
			label:"Adăugarea unor informații controversate fără note despre personalități în viață", 
			summary:"Avertizare: Afirmații controversate fără note despre personalități în viață" 
		},
		"au-mos3": { 
			label:"Manualul de stil", 
			summary:"Avertizare: Formatare, dată, limbă, etc. (Manualul de stil)" 
		},
		"au-afd3": { 
			label:"Ștergerea formatului \{\{Șterge\}\}", 
			summary:"Avertizare: Ștergerea formatului \{\{Șterge\}\}" 
		},
		"au-pdvn3": { 
			label:"Lipsă de neutralitate", 
			summary:"Avertizare: Lipsă de neutralitate" 
		},
		"au-trad3": { 
			label:"Traducere automată", 
			summary:"Avertizare: Traduceri automate" 
		},
		"au-vpd3": { 
			label:"Modificare mesajelor altora în paginile de discuții", 
			summary:"Avertizare: Modificare mesajelor altora în paginile de discuții" 
		},
		"au-discuții3": { 
			label:"Utilizarea Wikipediei ca pe un forum", 
			summary:"Avertizare: Utilizarea Wikipediei ca pe un forum" 
		},
		"au-plătit3": {
			label:"Contribuții plătite",
			summary:"Avertizare: Nu continuați înainte de a declara contribuțiile plătite"
		},
	},
	level4: {
		"au-vandalism4": { 
			label:"Vandalism", 
			summary:"Ultimul avertisment: Vandalism" 
		},
		"au-eroare4": {
			label:"Eroare",
			summary:"Ultimul avertisment: informații false"
		},
		"au-test4": { 
			label:"Modificări de test", 
			summary:"Ultimul avertisment: Modificări de test" 
		},
		"au-ștergeri4": { 
			label:"Ștergerea conținutului paginilor", 
			summary:"Ultimul avertisment: Ștergerea conținutului paginilor" 
		},
		"au-tdel4": { 
			label:"Ștergerea formatelor de întreținere", 
			summary:"Ultimul avertisment: Ștergerea formatelor de întreținere" 
		},
		"au-glumă4": { 
			label:"Glume nepotrivite", 
			summary:"Ultimul avertisment: Glume nepotrivite" 
		},
		"au-pg-nouă4": { 
			label:"Crearea unor pagini nepotrivite", 
			summary:"Ultimul avertisment: Crearea unor pagini nepotrivite" 
		},
		"au-reclamă4": { 
			label:"Adăugarea de reclame", 
			summary:"Ultimul avertisment: Adăugarea de reclame" 
		},
		"au-surse4": { 
			label:"Adăugarea unor materiale fără sursă și fără note de subsol", 
			summary:"Ultimul avertisment: Adăugarea unor materiale fără sursă și fără note de subsol" 
		},
		"au-biog4": { 
			label:"Adăugarea unor informații controversate fără note despre personalități în viață", 
			summary:"Ultimul avertisment: Afirmații controversate fără note despre personalități în viață" 
		},
		"au-pdvn4": { 
			label:"Lipsă de neutralitate", 
			summary:"Ultimul avertisment: Lipsă de neutralitate" 
		},
		"au-trad4": { 
			label:"Traducere automată", 
			summary:"Ultimul avertisment: Traduceri automate" 
		},
		"au-discuții4": { 
			label:"Utilizarea Wikipediei ca pe un forum", 
			summary:"Ultimul avertisment: Utilizarea Wikipediei ca pe un forum" 
		},
		"au-plătit1": {
			label:"Contribuții plătite",
			summary:"Notă generală: Veți fi blocat dacă nu declarați contribuțiile plătite"
		},
	},
	level4im: {
		"au-vandalism4im": { 
			label:"Vandalism", 
			summary:"Singurul avertisment: Vandalism" 
		},
		"au-ștergeri4im": { 
			label:"Ștergerea conținutului paginilor", 
			summary:"Singurul avertisment: Ștergerea conținutului paginilor" 
		},
		"au-pg-nouă4im": { 
			label:"Crearea unor pagini nepotrivite", 
			summary:"Singurul avertisment: Crearea unor pagini nepotrivite" 
		},
		"au-reclamă4im": { 
			label:"Adăugarea de reclame", 
			summary:"Avertizare: Adăugarea de reclame" 
		},

	},
	singlenotice: {
		"au-talkinarticle": { 
			label:"Discuții în articol", 
			summary:"Notificare: Discuții în articol" 
		},
		"au-test0": {
			label:"Teste autoanulate",
			summary:"Notificare: Teste doar la cutia cu nisip"
		},
		"au-anularevandalism": {
			label: "Revert complet la vandalism",
			summary: "Notificare: Anulați vandalismul cu ajutorul istoricului"
		},
		"nu-commons": { 
			label:"Utilizați Commons", 
			summary:"Notificare: Utilizați Commons" 
		},
		"previzualizare": { 
			label:"Folositi previzualizarea", 
			summary:"Notificare: Folosiți previzualizarea" 
		},
		"descriere": { 
			label:"Completați descrierea modificărilor", 
			summary:"Notificare: Completați descrierea modificărilor" 
		},
		"folosiți diacritice": { 
			label:"Scrieți cu diacritice", 
			summary:"Notificare: Scrieți cu diacritice" 
		},
		"mesajevandal": { 
			label:"Avertizați vandalii", 
			summary:"Notificare: Avertizați vandalii" 
		},
		"au-tilde": { 
			label:"Nesemnarea corespunzătoare a mesajelor", 
			summary:"Notificare: Semnătura în paginile de discuții"
		},
	},
	singlewarn: {
		"obscen": { 
			label:"Vandalism cu obscenități", 
			summary:"Avertizare: Proferare de obscenități" 
		},
		"au-copyright": { 
			label:"Încălcarea drepturilor de autor", 
			summary:"Avertizare: Încălcarea drepturilor de autor" 
		},
		"au-lexarticol": {
			label:"Legături externe în corpul articolului",
			summary:"Avertizare: Legături externe în corpul articolului"
		},
		"cont public": { 
			label:"Cont public", 
			summary:"Avertizare: Cont public" 
		},
		"testnn": { 
			label:"Abordare de subiecte nenotabile", 
			summary:"Avertizare: Abordare de subiecte nenotabile"
		},
		"au-badlistentry": {
			label:"Adăugarea de elemente nenotabile în liste",
			summary:"Avertizare: subiect nenotabil în listă"
		},
		"au-repost": { 
			label:"Reintroducere de material șters în urma discuției", 
			summary:"Avertizare: Reintroducere de material șters în urma discuției"
		},
		"au-c&pmove": { 
			label:"Redenumire prin copy-paste", 
			summary:"Avertizare: Redenumire prin ''copy'' și ''paste''"
		},
		"au-userpage": { 
			label:"Pagina de utilizator încalcă politicile", 
			summary:"Avertizare: Pagina de utilizator"
		},
	},
	block: {
		"blocat": {
			'label':"Blocare",
			'summary':"Blocare"
		},
	}
};

// Set to true if the template is always for an indef block
Twinkle.warn.indefBlockHash = {
	'uw-block': false,
	'uw-3block': false,
	'uw-ablock': false,
	'uw-adblock': false,
	'uw-aeblock': false,
	'uw-bioblock': false,
	'uw-blocknotalk': false,
	'uw-botblock': false,
	'uw-copyrightblock': false,
	'uw-dblock': false,
	'uw-efblock': false,
	'uw-ewblock': false,
	'uw-hblock': false,
	'uw-myblock': false,
	'uw-npblock': false,
	'uw-pinfoblock': false,
	'uw-sblock': false,
	'uw-pblock': false,
	'uw-blockindef': true,
	'uw-block-onlyfor': true,
	'uw-botublock': true,
	'uw-causeblock': true,
	'uw-compblock': true,
	'uw-deoablock': true,
	'uw-lblock': true,
	'uw-memorialblock': true,
	'uw-soablock': true,
	'uw-softerblock': true,
	'uw-spamublock': true,
	'uw-spoablock': true,
	'uw-ublock': true,
	'uw-ublock-famous': true,
	'uw-uhblock': true,
	'uw-uhblock-double': true,
	'uw-ublock-double': true,
	'uw-vaublock': true,
	'uw-voablock': true
};

// Set to true if the template supports the page parameter
Twinkle.warn.pageHash = {
	'uw-block': true,
	'uw-3block': true,
	'uw-ablock': true,
	'uw-adblock': true,
	'uw-aeblock': true,
	'uw-bioblock': true,
	'uw-blocknotalk': true,
	'uw-botblock': true,
	'uw-copyrightblock': true,
	'uw-dblock': true,
	'uw-efblock': true,
	'uw-ewblock': true,
	'uw-hblock': true,
	'uw-myblock': true,
	'uw-npblock': true,
	'uw-pinfoblock': true,
	'uw-sblock': true,
	'uw-vblock': true,
	'uw-blockindef': true,
	'uw-block-onlyfor': true,
	'uw-botublock': false,
	'uw-causeblock': false,
	'uw-compblock': true,
	'uw-deoablock': true,
	'uw-lblock': true,
	'uw-memorialblock': false,
	'uw-soablock': true,
	'uw-softerblock': false,
	'uw-spamublock': false,
	'uw-spoablock': true,
	'uw-ublock': false,
	'uw-ublock-famous': false,
	'uw-uhblock': false,
	'uw-uhblock-double': false,
	'uw-ublock-double': false,
	'uw-vaublock': true,
	'uw-voablock': true
};

// Set to true if the template supports the reason parameter and isn't the same as its super-template when a reason is provided
Twinkle.warn.reasonHash = {
	'blocat': true
};

Twinkle.warn.prev_block_timer = null;
Twinkle.warn.prev_article = null;
Twinkle.warn.prev_reason = null;

Twinkle.warn.callback.change_category = function twinklewarnCallbackChangeCategory(e) {
	var value = e.target.value;
	var sub_group = e.target.root.sub_group;
	var messages = Twinkle.warn.messages[ value ];
	sub_group.main_group = value;
	var old_subvalue = sub_group.value;
	var old_subvalue_re;
	if( old_subvalue ) {
		old_subvalue = old_subvalue.replace(/\d*(im)?$/, '' );
		old_subvalue_re = new RegExp( RegExp.escape( old_subvalue ) + "(\\d*(?:im)?)$" );
	}

	while( sub_group.hasChildNodes() ){
		sub_group.removeChild( sub_group.firstChild );
	}

	for( var i in messages ) {
		var selected = false;
		if( old_subvalue && old_subvalue_re.test( i ) ) {
			selected = true;
		}
		var elem = new Morebits.quickForm.element( { type:'option', label:"[" + i + "]: " + messages[i].label, value:i, selected: selected } );
		
		sub_group.appendChild( elem.render() );
	}

	if( value === 'block' ) {
		var more = new Morebits.quickForm.element( {
				type: 'input',
				name: 'block_timer',
				label: 'Perioada blocării: ',
				tooltip: 'Perioada pe care se efectuează blocarea, de exemplu 24 de ore, 2 săptămâni, nelimitat etc...'
			} );
		e.target.root.insertBefore( more.render(), e.target.root.lastChild );
		if(Twinkle.warn.prev_block_timer !== null) {
			e.target.root.block_timer.value = Twinkle.warn.prev_block_timer;
			Twinkle.warn.prev_block_timer = null;
		}		
		if(Twinkle.warn.prev_article === null) {
			Twinkle.warn.prev_article = e.target.root.article.value;
		}
		e.target.root.article.disabled = true;
		e.target.root.article.value = '';
	} else if( e.target.root.block_timer ) {
		if(!e.target.root.block_timer.disabled && Twinkle.warn.prev_block_timer === null) {
			Twinkle.warn.prev_block_timer = e.target.root.block_timer.value;
		}
		e.target.root.removeChild( e.target.root.block_timer.parentNode );
		if(e.target.root.article.disabled && Twinkle.warn.prev_article !== null) {
			e.target.root.article.value = Twinkle.warn.prev_article;
			Twinkle.warn.prev_article = null;
		}
		e.target.root.article.disabled = false;
		if(e.target.root.reason.disabled && Twinkle.warn.prev_reason !== null) {
			e.target.root.reason.value = Twinkle.warn.prev_reason;
			Twinkle.warn.prev_reason = null;
		}
		e.target.root.reason.disabled = false;
	}
};

Twinkle.warn.callback.change_subcategory = function twinklewarnCallbackChangeSubcategory(e) {
	var main_group = e.target.main_group;
	var value = e.target.value;

	if( main_group === 'singlewarn' ) {
		if( value === 'uw-username' ) {
			if(Twinkle.warn.prev_article === null) {
				Twinkle.warn.prev_article = e.target.form.article.value;
			}
			e.target.form.article.disabled = true;
			e.target.form.article.value = '';
		} else if( e.target.form.article.disabled ) {
			if(Twinkle.warn.prev_article !== null) {
				e.target.form.article.value = Twinkle.warn.prev_article;
				Twinkle.warn.prev_article = null;
			}
			e.target.form.article.disabled = false;
		}
	} else if( main_group === 'block' ) {
		if( Twinkle.warn.indefBlockHash[ value ] ) {
			if(Twinkle.warn.prev_block_timer === null) {
				Twinkle.warn.prev_block_timer = e.target.form.block_timer.value;
			}
			e.target.form.block_timer.disabled = true;
			e.target.form.block_timer.value = 'indef';
		} else if( e.target.form.block_timer.disabled ) {
			if(Twinkle.warn.prev_block_timer !== null) {
				e.target.form.block_timer.value = Twinkle.warn.prev_block_timer;
				Twinkle.warn.prev_block_timer = null;
			}
			e.target.form.block_timer.disabled = false;
		}

		if( Twinkle.warn.pageHash[ value ] ) {
			if(Twinkle.warn.prev_article !== null) {
				e.target.form.article.value = Twinkle.warn.prev_article;
				Twinkle.warn.prev_article = null;
			}
			e.target.form.article.disabled = false;
		} else if( !e.target.form.article.disabled ) {
			if(Twinkle.warn.prev_article === null) {
				Twinkle.warn.prev_article = e.target.form.article.value;
			}
			e.target.form.article.disabled = true;
			e.target.form.article.value = '';
		}

		if( Twinkle.warn.reasonHash[ value ] ) {
			if(Twinkle.warn.prev_reason !== null) {
				e.target.form.reason.value = Twinkle.warn.prev_reason;
				Twinkle.warn.prev_reason = null;
			}
			e.target.form.reason.disabled = false;
		} else if( !e.target.form.reason.disabled ) {
			if(Twinkle.warn.prev_reason === null) {
				Twinkle.warn.prev_reason = e.target.form.reason.value;
			}
			e.target.form.reason.disabled = true;
			e.target.form.reason.value = '';
		}
	}

	var $article = $(e.target.article);
	if (main_group === "singlewarn" && value === "uw-socksuspect") {
		$article.prev().hide();
		$article.before('<span id="tw-spi-article-username">Username of sock master, if known (without User:) </span>');
	} else {
		$("span#tw-spi-article-username").remove();
		$article.prev().show();
	}
};

Twinkle.warn.callbacks = {
	preview: function() {
		// XXX cannot preview block templates as yet...
		var templatename = $('select[name="sub_group"]:visible').last()[0].value;
		if (templatename in Twinkle.warn.messages.block) {
			alert("Cannot preview block templates at the moment, unfortunately");
			return;
		}

		var previewdiv = $('div[name="warningpreview"]:visible').last();
		if (!previewdiv.length) {
			return;  // just give up
		}
		previewdiv = previewdiv[0];

		var previewbox = $('div#twinklewarn-previewbox:visible').last();
		if (!previewbox.length) {
			previewbox = document.createElement('div');
			previewbox.style.background = "white";
			previewbox.style.border = "2px inset";
			previewbox.style.marginTop = "0.4em";
			previewbox.style.padding = "0.2em 0.4em";
			previewbox.setAttribute('id', 'twinklewarn-previewbox');
			previewdiv.parentNode.appendChild(previewbox);
		} else {
			previewbox = previewbox[0];
		}

		var statusspan = document.createElement('span');
		previewbox.appendChild(statusspan);
		Morebits.status.init(statusspan);
		var templatetext = '{{subst:' + templatename;
		var linkedarticle = $('input[name="article"]:visible').last();
		if (linkedarticle.length) {
			templatetext += '|1=' + linkedarticle[0].value;
		}
		templatetext += '}}';
		var reason = $('textarea[name="reason"]:visible').last();
		if (reason.length && reason[0].value) {
			templatetext += " ''" + reason[0].value + "''";
		}
		var query = {
			action: 'parse',
			prop: 'text',
			pst: 'true',  // PST = pre-save transform; this makes substitution work properly
			text: templatetext,
			title: mw.config.get('wgPageName')
		};
		var wikipedia_api = new Morebits.wiki.api("încărcare...", query, Twinkle.warn.callbacks.previewRender, new Morebits.status("Previzualizare"));
		wikipedia_api.params = { previewbox: previewbox };
		wikipedia_api.post();
	},
	previewRender: function( apiobj ) {
		var params = apiobj.params;
		var xml = apiobj.getXML();
		var html = $(xml).find('text').text();
		if (!html) {
			apiobj.statelem.error("failed to retrieve preview, or warning template was blanked");
			return;
		}
		params.previewbox.innerHTML = html;
		// fix vertical alignment
		$(params.previewbox).find(':not(img)').css('vertical-align', 'baseline');
	},
	main: function( pageobj ) {
		var text = pageobj.getPageText();
		var params = pageobj.getCallbackParameters();
		var messageData = Twinkle.warn.messages[params.main_group][params.sub_group];

		var history_re = /<!-- Template:(uw-.*?) -->.*?(\d{1,2}:\d{1,2}, \d{1,2} \w+ \d{4}) \(UTC\)/g;
		var history = {};
		var latest = { date:new Date( 0 ), type:'' };
		var current;

		while( ( current = history_re.exec( text ) ) ) {
			var current_date = new Date( current[2] + ' UTC' );
			if( !( current[1] in history ) ||  history[ current[1] ] < current_date ) {
				history[ current[1] ] = current_date;
			}
			if( current_date > latest.date ) {
				latest.date = current_date;
				latest.type = current[1];
			}
		}

		var date = new Date();

		if( params.sub_group in history ) {
			var temp_time = new Date( history[ params.sub_group ] );
			temp_time.setUTCHours( temp_time.getUTCHours() + 24 );

			if( temp_time > date ) {
				if( !confirm( "An identical " + params.sub_group + " has been issued in the last 24 hours.  \nWould you still like to add this warning/notice?" ) ) {
					pageobj.statelem.info( 'aborted per user request' );
					return;
				}
			}
		}

		latest.date.setUTCMinutes( latest.date.getUTCMinutes() + 1 ); // after long debate, one minute is max

		if( latest.date > date ) {
			if( !confirm( "A " + latest.type + " has been issued in the last minute.  \nWould you still like to add this warning/notice?" ) ) {
				pageobj.statelem.info( 'aborted per user request' );
				return;
			}
		}
		
		var mainheaderRe = new RegExp("==+\\s*Warnings\\s*==+");
		var headerRe = new RegExp( "^==+\\s*(?:" + date.getUTCMonthName() + '|' + date.getUTCMonthNameAbbrev() +  ")\\s+" + date.getUTCFullYear() + "\\s*==+", 'm' );

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

		if( params.main_group === 'block' ) {
			var article = '', reason = '', time = null;
			
			if( params.article && Twinkle.warn.pageHash[ params.sub_group ] ) {
				article = '|page=' + params.article;
			}
			
			if( params.reason && Twinkle.warn.reasonHash[ params.sub_group ] ) {
				reason = '|reason=' + params.reason;
			}
			
			if( /te?mp|^\s*$|min/.exec( params.block_timer ) || Twinkle.warn.indefBlockHash[ params.sub_group ] ) {
				time = '';
			} else if( /indef|\*|max/.exec( params.block_timer ) ) {
				time = '|1=nelimitat';
			} else {
				time = '|1=' + params.block_timer;
			}

			text += "{{subst:" + params.sub_group + article + time + reason + "|sig=true|subst=subst:}}";
		} else {
			switch( params.sub_group ) {
				case 'uw-username':
					text += "{{subst:" + params.sub_group + ( params.reason ? '|1=' + params.reason : '' ) + "|subst=subst:}} ~~~~";
					break;
				case 'uw-socksuspect':
					text += "{{subst:" + params.sub_group + ( params.article ? '|1=User:' + params.article : '' ) + "|subst=subst:}}" + (params.reason ? " ''" + params.reason + "'' ": ' ' ) + " ~~~~";
					break;
				default:
					text += "{{subst:" + params.sub_group + ( params.article ? '|1=' + params.article : '' ) + "|subst=subst:}}" + (params.reason ? " ''" + params.reason + "'' ": ' ' ) + "~~~~";
					break;
			}
		}
		
		if ( Twinkle.getPref('showSharedIPNotice') && mw.util.isIPAddress( mw.config.get('wgTitle') ) ) {
			Morebits.status.info( 'Info', 'Adding a shared IP notice' );
			text +=  "\n{{subst:SharedIPAdvice}}";
		}

		var summary = messageData.summary;
		if ( messageData.suppressArticleInSummary !== true && params.article ) {
			if ( params.sub_group === "uw-socksuspect" ) {  // this template requires a username
				summary += " de către [[Utilizator:" + params.article + "]]";
			} else {
				summary += " la [[" + params.article + "]]";
			}
		}
		summary += "." + Twinkle.getPref("summaryAd");

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

Twinkle.warn.callback.evaluate = function twinklewarnCallbackEvaluate(e) {

	// First, check to make sure a reason was filled in if uw-username was selected
	
	if(e.target.sub_group.value === 'uw-username' && e.target.reason.value.trim() === '') {
		alert("You must supply a reason for the {{uw-username}} template.");
		return;
	}

	// Then, grab all the values provided by the form
	
	var params = {
		reason: e.target.reason.value,
		main_group: e.target.main_group.value,
		sub_group: e.target.sub_group.value,
		article: e.target.article.value.replace( /^(Image|Category):/i, ':$1:' ),
		block_timer: e.target.block_timer ? e.target.block_timer.value : null
	};

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( e.target );

	Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
	Morebits.wiki.actionCompleted.notice = "Avertizare realizată, pagina de discuții se va reîncărca în câteva secunde";

	var wikipedia_page = new Morebits.wiki.page( mw.config.get('wgPageName'), 'Modificarea paginii de utilizator' );
	wikipedia_page.setCallbackParameters( params );
	wikipedia_page.setFollowRedirect( true );
	wikipedia_page.load( Twinkle.warn.callbacks.main );
};

/*
 ****************************************
 *** twinklexfd.js: XFD module
 ****************************************
 * Mode of invocation:     Tab ("XFD")
 * Active on:              Existing, non-special pages, except for file pages with no local (non-Commons) file which are not redirects
 * Config directives in:   TwinkleConfig
 */

Twinkle.xfd = function twinklexfd() {
	// Disable on:
	// * special pages
	// * non-existent pages
	// * files on Commons, whether there is a local page or not (unneeded local pages of files on Commons are eligible for CSD F2)
	// * file pages without actual files (these are eligible for CSD G8)
	if ( mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && (document.getElementById('mw-sharedupload') || (!document.getElementById('mw-imagepage-section-filehistory') && !Morebits.wiki.isPageRedirect()))) ) {
		return;
	}
	if (twinkleUserAuthorized) {
		twAddPortletLink(Twinkle.xfd.callback, "PȘ", "tw-xfd", "Propune pentru ștergere");
	} else {
		twAddPortletLink(function() {
			alert("Contul dumneavoastră este prea recent pentru a folosi Twinkle.");
		}, 'PȘ', 'tw-xfd', 'Propune pentru ștergere');
	}
};

Twinkle.xfd.num2order = function twinklexfdNum2order( num ) {
	switch( num ) {
	case 1: return '';
	default: return '' +num + '';
	}
};

Twinkle.xfd.currentRationale = null;

// error callback on Status object
Twinkle.xfd.printRationale = function twinklexfdPrintRationale() {
	if (Twinkle.xfd.currentRationale) {
		var p = document.createElement("p");
		p.textContent = "Aveți motivația pentru ștergere dedesubt, și o puteți copia într-un nou dialog similar dacă doriți să mai încercați:";
		var pre = document.createElement("pre");
		pre.className = "toccolours";
		pre.style.marginTop = "0";
		pre.textContent = Twinkle.xfd.currentRationale;
		p.appendChild(pre);
		Morebits.status.root.appendChild(p);
		// only need to print the rationale once
		Twinkle.xfd.currentRationale = null;
	}
};

Twinkle.xfd.callback = function twinklexfdCallback() {
	var Window = new Morebits.simpleWindow( 600, 350 );
	Window.setTitle( "Propune pentru ștergere (PȘ)" );
	Window.setScriptName( "Twinkle" );
	Window.addFooterLink( "Despre discuțiile despre ștergere", "Wikipedia:Ștergere" );
	Window.addFooterLink( "Twinkle help", "WP:TW/DOC#xfd" );

	var form = new Morebits.quickForm( Twinkle.xfd.callback.evaluate );
	var categories = form.append( {
			type: 'select',
			name: 'category',
			label: 'Locul discuției:',
			tooltip: 'Când este activat, se face o opțiune implicită, pe baza spațiului de nume în care vă aflați. Valoarea implicită e de regulă cea mai potrivită',
			event: Twinkle.xfd.callback.change_category
		} );
	categories.append( {
			type: 'option',
			label: 'Propunere generică de ștergere',
			selected: true,//mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").MAIN,
			value: 'afd'
		} );/*
	categories.append( {
			type: 'option',
			label: 'TfD (Templates for discussion)',
			selected: mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").TEMPLATE,
			value: 'tfd'
		} );
	categories.append( {
			type: 'option',
			label: 'FfD (Files for deletion)/PUF (Possibly unfree files)',
			selected: mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").IMAGE,
			value: 'ffd'
		} );
	categories.append( {
			type: 'option',
			label: 'CfD (Categories for discussion)',
			selected: mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").CATEGORY,
			value: 'cfd'
		} );
	categories.append( {
			type: 'option',
			label: 'MfD (Miscellany for deletion)',
			selected: [ mw.config.get("wgNamespaceIds").IMAGE, mw.config.get("wgNamespaceIds").MAIN, mw.config.get("wgNamespaceIds").TEMPLATE, mw.config.get("wgNamespaceIds").CATEGORY ].indexOf( mw.config.get('wgNamespaceNumber') ) === -1 ,
			value: 'mfd'
		} );
	categories.append( {
			type: 'option',
			label: 'RfD (Redirects for discussion)',
			selected: Wikipedia.isPageRedirect(),
			value: 'rfd'
		} );*/
	//categories.append( {
	//		type: 'option',
	//		label: 'SfD (Stub types for deletion)',
	//		disabled: true,
	//		value: 'sfd'
	//	} );
	form.append( {
			type: 'checkbox',
			list: [
				{
					label: 'Anunță creatorul paginii',
					value: 'notify',
					name: 'notify',
					tooltip: "Se va plasa un format de notificare în pagina de discuție a utilizatorului.",
					checked: true
				}
			]
		}
	);
	form.append( {
			type: 'field',
			label:'Work area',
			name: 'work_area'
		} );
	form.append( { type:'submit' } );

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

	// We must init the controls
	var evt = document.createEvent( "Event" );
	evt.initEvent( 'change', true, true );
	result.category.dispatchEvent( evt );
};

Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory(e) {
	var value = e.target.value;
	var root = e.target.form;
	var old_area;
	var childNodes = root.childNodes;
	for( var i = 0; i < childNodes.length; ++i ) {
		var node = childNodes[i];
		if (node instanceof Element &&
		    node.getAttribute( 'name' ) === 'work_area') {
			old_area = node;
			break;
		}
	}
	var work_area = null;

	var oldreasontextbox = e.target.form.getElementsByTagName('textarea')[0];
	var oldreason = (oldreasontextbox ? oldreasontextbox.value : '');

	switch( value ) {
	case 'afd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Articole de șters',
				name: 'work_area'
			} );
		work_area.append( {
				type: 'checkbox',
				list: [
						{
							label: 'Include formatul de ștergere în etichete <noinclude>',
							value: 'noinclude',
							name: 'noinclude',
							tooltip: 'Înconjoară eticheta de ștergere cu taguri &lt;noinclude&gt; tags, ca să nu fie transclusă. De regulă, opțiunea nu este necesară.'
						}
					]
		} );
/*
		var afd_category = work_area.append( {
				type:'select',
				name:'xfdcat',
				label:'Choose what category this nomination belongs in:'
			} );

		afd_category.append( { type:'option', label:'Unknown', value:'?', selected:true } );
		afd_category.append( { type:'option', label:'Media and music', value:'M' } );
		afd_category.append( { type:'option', label:'Organisation, corporation, or product', value:'O' } );
		afd_category.append( { type:'option', label:'Biographical', value:'B' } );
		afd_category.append( { type:'option', label:'Society topics', value:'S' } );
		afd_category.append( { type:'option', label:'Web or internet', value:'W' } );
		afd_category.append( { type:'option', label:'Games or sports', value:'G' } );
		afd_category.append( { type:'option', label:'Science and technology', value:'T' } );
		afd_category.append( { type:'option', label:'Fiction and the arts', value:'F' } );
		afd_category.append( { type:'option', label:'Places and transportation', value:'P' } );
		afd_category.append( { type:'option', label:'Indiscernible or unclassifiable topic', value:'I' } );
		afd_category.append( { type:'option', label:'Debate not yet sorted', value:'U' } );
*/
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Motiv: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'tfd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Templates for discussion',
				name: 'work_area'
			} );
		var linknode = document.createElement('a');
		linknode.setAttribute("href", mw.util.getUrl("WP:SFD") );
		linknode.appendChild(document.createTextNode('WP:SFD'));
		work_area.append( {
				type: 'div',
				label: [ 'Stub types and userboxes are not eligible for TfD. Stub types go to ', linknode, ', and userboxes go to MfD.' ]
			} );
		work_area.append( {
				type: 'checkbox',
				list: [
						{
							label: 'Inline deletion tag',
							value: 'tfdinline',
							name: 'tfdinline',
							tooltip: 'Use {{tfd|type=inline}} to tag the page instead of {{tfd}}. Good for inline templates (those that appear amongst the words of text).',
							checked: false
						}
					]
		} );
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Reason: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'mfd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Miscellany for deletion',
				name: 'work_area'
			} );
		work_area.append( {
				type: 'checkbox',
				list: [
						{
							label: 'Wrap deletion tag with <noinclude>',
							value: 'noinclude',
							name: 'noinclude',
							tooltip: 'Will wrap the deletion tag in &lt;noinclude&gt; tags, so that it won\'t transclude. Select this option for userboxes.'
						}
					]
		} );
		if (mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").USER || mw.config.get('wgNamespaceNumber') === mw.config.get("wgNamespaceIds").USER_TALK) {
			work_area.append( {
				type: 'checkbox',
				list: [
						{
							label: 'Also notify owner of userspace if they are not the page creator',
							value: 'notifyuserspace',
							name: 'notifyuserspace',
							tooltip: 'If the user in whose userspace this page is located, is not the page creator (for example, the page is a rescued article stored as a userspace draft), notify the userspace owner as well.',
							checked: true
						}
					]
			} );
		}
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Reason: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'ffd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Files for deletion',
				name: 'work_area'
			} );
		work_area.append( {
				type: 'checkbox',
				name: 'puf',
				list: [
					{
						label: 'Possibly unfree file',
						value: 'puf',
						tooltip: 'File has disputed source or licensing information'
					}
				]
			} );
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Reason: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'cfd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Categories for discussion',
				name: 'work_area'
			} );
		var cfd_category = work_area.append( {
				type: 'select',
				label: 'Choose type of action wanted: ',
				name: 'xfdcat',
				event: function(e) {
					var value = e.target.value;
					var target = e.target.form.xfdtarget;
					if( value === 'cfd' ) {
						target.disabled = true;
					} else {
						target.disabled = false;
					}
				}
			} );
		cfd_category.append( { type: 'option', label: 'Deletion', value: 'cfd', selected: true } );
		cfd_category.append( { type: 'option', label: 'Merge', value: 'cfm' } );
		cfd_category.append( { type: 'option', label: 'Renaming', value: 'cfr' } );
		cfd_category.append( { type: 'option', label: 'Convert into article', value: 'cfc' } );

		work_area.append( {
				type: 'input',
				name: 'xfdtarget',
				label: 'Target page: ',
				disabled: true,
				value: ''
			} );
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Reason: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	case 'rfd':
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Redirects for discussion',
				name: 'work_area'
			} );
		work_area.append( {
				type: 'textarea',
				name: 'xfdreason',
				label: 'Reason: ',
				value: oldreason
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	default:
		work_area = new Morebits.quickForm.element( {
				type: 'field',
				label: 'Nimic pentru orice',
				name: 'work_area'
			} );
		work_area = work_area.render();
		old_area.parentNode.replaceChild( work_area, old_area );
		break;
	}
};

Twinkle.xfd.callbacks = {
	afd: {
		main: function(apiobj) {
			Morebits.status.info("-------------xfd main callback");
			var xmlDoc = apiobj.responseXML;
			var titles = $(xmlDoc).find('allpages p');
			Morebits.status.info("-------------found titles: " + titles.length);

			// There has been no earlier entries with this prefix, just go on.
			if( titles.length <= 0 ) {
				apiobj.params.numbering = apiobj.params.number = '';
			} else {
				var number = 0;
				for( var i = 0; i < titles.length; ++i ) {
					var title = titles[i].getAttribute('title');

					// First, simple test, is there an instance with this exact name?
					if( title === 'Wikipedia:Pagini de șters/' + mw.config.get('wgPageName') ) {
						number = Math.max( number, 1 );
						continue;
					}

					var order_re = new RegExp( '^' +
						RegExp.escape( 'Wikipedia:Pagini de \u0219ters/' + mw.config.get('wgPageName'), true ) +
						'\\s*\\(\\s*(\\d+)\\s*\\)\\s*$');
					var match = order_re.exec( title );

					// No match; A non-good value
					if( !match ) {
						continue;
					}

					// A match, set number to the max of current
					number = Math.max( number, Number(match[1]) );
				}
				apiobj.params.number = Twinkle.xfd.num2order( parseInt( number, 10 ) + 1);
				apiobj.params.numbering = number > 0 ? ' (' + apiobj.params.number + ')' : '';
			}
			apiobj.params.discussionpage = 'Wikipedia:Pagini de \u0219ters/' + mw.config.get('wgPageName') + apiobj.params.numbering;

			Morebits.status.info( "Următoarea pagină de discuții", "[[" + apiobj.params.discussionpage + "]]" );

			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = apiobj.params.discussionpage;
			Morebits.wiki.actionCompleted.notice = "Propunere realizată, redirecționez spre pagina de discuție";

			// Tagging article
			var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Adaug eticheta de ștergere în articol");
			wikipedia_page.setFollowRedirect(true);  // should never be needed, but if the article is moved, we would want to follow the redirect
			wikipedia_page.setCallbackParameters(apiobj.params);
			wikipedia_page.load(Twinkle.xfd.callbacks.afd.taggingArticle);
		},
		// Tagging needs to happen before everything else: this means we can check if there is an AfD tag already on the page
		taggingArticle: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			// Check for existing AfD tag, for the benefit of new page patrollers
			var textNoAfd = text.replace(/\{\{\s*((\u0218|\u0219)terge)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");
			if (text !== textNoAfd) {
				if (confirm("O etichetă de ștergere a fost deja plasată în acest articol. Poate v-a luat-o altcineva înainte.  \nClick OK pentru a înlocui eticheta actuală (nu vă recomandăm), sau Cancel pentru a renunța la propunere.")) {
					text = textNoAfd;
				} else {
					statelem.error("Articol deja etichetat cu „șterge”, ați ales să renunțați");
					window.location.reload();
					return;
				}
			}

			// Now we know we want to go ahead with it, trigger the other AJAX requests

			// Starting discussion page
			var wikipedia_page = new Morebits.wiki.page(params.discussionpage, "Creez pagina de discuție a propunerii de ștergere");
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.afd.discussionPage);

			// Today's list
			var date = new Date();
			wikipedia_page = new Morebits.wiki.page('Wikipedia:Pagini de șters', "Adaug discuția la listă");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.afd.todaysList);

			// Notification to first contributor
			if (params.usertalk) {
				var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
				thispage.setCallbackParameters(params);
				thispage.lookupCreator(Twinkle.xfd.callbacks.afd.userNotification);
			}

			// Remove some tags that should always be removed on AfD.
			//text = text.replace(/\{\{\s*(dated prod|dated prod blp|Prod blp\/dated|Proposed deletion\/dated|prod2|Proposed deletion endorsed|New unreviewed article|Userspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, "");
			// Then, test if there are speedy deletion-related templates on the article.
			var textNoSd = text.replace(/\{\{\s*(\u2019r(-\w*)?|speedy)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, "");
			if (text !== textNoSd && confirm("În pagină a fost găsit un format pentru ștergerea rapidă. Să îl eliminăm?")) {
				text = textNoSd;
			}

			pageobj.setPageText((params.noinclude ? "<noinclude>{{șterge" : "{{șterge") + (params.number === '' ? '' : ('|discuție=' + mw.config.get('wgPageName')
				+ ' (' + params.number + ")")) + "|1=" + params.reason + (params.noinclude ? "}}</noinclude>\n" : "}}\n") + text);
			pageobj.setEditSummary("Propus pentru ștergere; vezi [[" + params.discussionpage + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		},
		discussionPage: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{subst:formular ștergere|1=" + mw.config.get('wgPageName') + "|3=" + params.reason + " ~~~~}}\n");
			pageobj.setEditSummary("Creez pagina de propunere a ștergerii pentru [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('createonly');
			pageobj.save(Twinkle.xfd.callbacks.afd.purgePage);
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		purgePage: function(pageobj) {
			var purgeQuery = {
				action: 'purge',
				redirects: true,
				titles: mw.config.get( 'wgPageName' ), // redirects are already resolved
			};
			new mw.Api().post(purgeQuery).then(function() {
				new mw.Api().post({action:'purge', titles: 'Wikipedia:Pagini de șters', redirects: true}).then(function() {
					location.reload();
				});
			});
		},
		todaysList: function(pageobj) {
			var old_text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			var text = old_text.replace( /(== Discu\u021bii curente ==\n+)/, "$1{{ {{subst:Pagină de discuție a propunerii de ștergere|pg=" + mw.config.get('wgPageName') + "|număr=" + params.numbering + "}} }}\n");
			if( text === old_text ) {
				statelem.error( 'nu am găsit locul unde să plasez discuția' );
				return;
			}
			pageobj.setPageText(text);
			pageobj.setEditSummary("Adaug [[" + params.discussionpage + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchList')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
		},
		userNotification: function(pageobj) {
			var params = pageobj.getCallbackParameters();
			var initialContrib = pageobj.getCreator();
			var usertalkpage = new Morebits.wiki.page('Discuție Utilizator:' + initialContrib, "Notific primul redactor din istoric (" + initialContrib + ")");
			var notifytext = "\n{{subst:AFDWarning|1=" + mw.config.get('wgPageName') + ( params.numbering !== '' ? '|order=&#32;' + params.numbering : '' ) + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notificare: [[Wikipedia:Pagini de șters|propunere pentru ștergere]] a paginii [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	},


	tfd: {
		taggingTemplate: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{tfd" + (params.tfdinline ? "|type=inline" : "") + "|" + mw.config.get('wgTitle') + "}}\n" + text);
			pageobj.setEditSummary("Propus pentru ștergere; vezi [[" + params.logpage + "#" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		},
		todaysList: function(pageobj) {
			var old_text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			var text = old_text.replace( '-->', "-->\n{{subst:tfd2|" + mw.config.get('wgTitle') + "|text=" + params.reason + " ~~~~}}");
			if( text === old_text ) {
				statelem.error( 'failed to find target spot for the discussion' );
				return;
			}
			pageobj.setPageText(text);
			pageobj.setEditSummary("Adding [[Template:" + mw.config.get('wgTitle') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		userNotification: function(pageobj) {
			var initialContrib = pageobj.getCreator();
			var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")");
			var notifytext = "\n{{subst:tfdnotice|1=" + mw.config.get('wgTitle') + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notificare: punere în discuție a formatului [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	},


	mfd: {
		main: function(apiobj) {
			var xmlDoc = apiobj.responseXML;
			var titles = $(xmlDoc).find('allpages p');

			// There has been no earlier entries with this prefix, just go on.
			if( titles.length <= 0 ) {
				apiobj.params.numbering = apiobj.params.number = '';
				numbering = number = '';
			} else {
				var number = 0;
				for( var i = 0; i < titles.length; ++i ) {
					var title = titles[i].getAttribute('title');

					// First, simple test, is there an instance with this exact name?
					if( title === 'Wikipedia:Miscellany for deletion/' + mw.config.get('wgPageName') ) {
						number = Math.max( number, 1 );
						continue;
					}

					var order_re = new RegExp( '^' +
							RegExp.escape( 'Wikipedia:Miscellany for deletion/' + mw.config.get('wgPageName'), true ) +
							'\\s*\\(\\s*(\\d+)(?:(?:th|nd|rd|st) nom(?:ination)?)?\\s*\\)\\s*$' );
					var match = order_re.exec( title );

					// No match; A non-good value
					if( !match ) {
						continue;
					}

					// A match, set number to the max of current
					number = Math.max( number, Number(match[1]) );
				}
				apiobj.params.number = Twinkle.xfd.num2order( parseInt( number, 10 ) + 1);
				apiobj.params.numbering = number > 0 ? ' (' + apiobj.params.number + ' nomination)' : '';
			}
			apiobj.params.discussionpage = "Wikipedia:Miscellany for deletion/" + mw.config.get('wgPageName') + apiobj.params.numbering;

			apiobj.statelem.info( "next in order is [[" + apiobj.params.discussionpage + ']]');

			// Tagging page
			var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Tagging page with deletion tag");
			wikipedia_page.setFollowRedirect(true);  // should never be needed, but if the page is moved, we would want to follow the redirect
			wikipedia_page.setCallbackParameters(apiobj.params);
			wikipedia_page.load(Twinkle.xfd.callbacks.mfd.taggingPage);

			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = apiobj.params.discussionpage;
			Morebits.wiki.actionCompleted.notice = "Nomination completed, now redirecting to the discussion page";

			// Discussion page
			wikipedia_page = new Morebits.wiki.page(apiobj.params.discussionpage, "Creating deletion discussion page");
			wikipedia_page.setCallbackParameters(apiobj.params);
			wikipedia_page.load(Twinkle.xfd.callbacks.mfd.discussionPage);

			// Today's list
			wikipedia_page = new Morebits.wiki.page("Wikipedia:Miscellany for deletion", "Adding discussion to today's list");
			//wikipedia_page.setPageSection(2);
				// pageSection has been disabled - the API seems to throw up with nonexistent edit conflicts
				// it can be turned on again once the problem is fixed, to save bandwidth
			//wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(apiobj.params);
			wikipedia_page.load(Twinkle.xfd.callbacks.mfd.todaysList);

			// Notification to first contributor, and notification to owner of userspace (if applicable and required)
			if (apiobj.params.usertalk) {
				var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
				thispage.setCallbackParameters(apiobj.params);
				thispage.lookupCreator(Twinkle.xfd.callbacks.mfd.userNotification);
			}
		},
		taggingPage: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText((params.noinclude ? "<noinclude>" : "") + "{{" + ((params.number === '') ? "mfd}}\n" : ('mfdx|' + params.number + "}}\n")) +
				(params.noinclude ? "</noinclude>" : "") + text);
			pageobj.setEditSummary("Nominated for deletion; see [[" + params.discussionpage + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		},
		discussionPage: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{subst:mfd2|pg=" + mw.config.get('wgPageName') + "|text=" + params.reason + " ~~~~}}\n");
			pageobj.setEditSummary("Creating deletion discussion page for [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('createonly');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		todaysList: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			var date = new Date();
			var date_header = "===" + date.getUTCMonthName() + ' ' + date.getUTCDate() + ', ' + date.getUTCFullYear() + "===";
			var date_header_regex = new RegExp( "(===\\s*" + date.getUTCMonthName() + '\\s+' + date.getUTCDate() + ',\\s+' + date.getUTCFullYear() + "\\s*===)" );
			var new_data = "{{subst:mfd3|pg=" + mw.config.get('wgPageName') + params.numbering + "}}";

			if( date_header_regex.test( text ) ) { // we have a section already
				statelem.info( 'Found today\'s section, proceeding to add new entry' );
				text = text.replace( date_header_regex, "$1\n" + new_data );
			} else { // we need to create a new section
				statelem.info( 'No section for today found, proceeding to create one' );
				text = text.replace("===", date_header + new_data + "\n\n===");
			}

			pageobj.setPageText(text);
			pageobj.setEditSummary("Adding [[" + params.discussionpage + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchList')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
		},
		userNotification: function(pageobj) {
			var initialContrib = pageobj.getCreator();
			var params = pageobj.getCallbackParameters();

			// Really notify the creator
			Twinkle.xfd.callbacks.mfd.userNotificationMain(params, initialContrib, "Notifying initial contributor");

			// Also notify the user who owns the subpage if they are not the creator
			if (params.notifyuserspace) {
				var userspaceOwner = ((mw.config.get('wgTitle').indexOf('/') === -1) ? mw.config.get('wgTitle') : mw.config.get('wgTitle').substring(0, mw.config.get('wgTitle').indexOf('/')));
				if (userspaceOwner !== initialContrib) {
					Twinkle.xfd.callbacks.mfd.userNotificationMain(params, userspaceOwner, "Notifying owner of userspace");
				}
			}
		},
		userNotificationMain: function(params, initialContrib, actionName)
		{
			var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, actionName + " (" + initialContrib + ")");
			var notifytext = "\n{{subst:MFDWarning|1=" + mw.config.get('wgPageName') + ( params.numbering !== '' ? '|order=&#32;' + params.numbering : '' ) + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notificare: propunere pentru ștergere a paginii [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	},


	ffd: {
		main: function(pageobj) {
			// this is coming in from lookupCreator...!
			var params = pageobj.getCallbackParameters();
			var initialContrib = pageobj.getCreator();
			params.uploader = initialContrib;

			// Adding discussion
			wikipedia_page = new Morebits.wiki.page(params.logpage, "Adding discussion to today's list");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.ffd.todaysList);

			// Notification to first contributor
			if(params.usertalk) {
				var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")");
				var notifytext = "\n{{subst:idw|1=" + mw.config.get('wgTitle') + "}}";
				usertalkpage.setAppendText(notifytext);
				usertalkpage.setEditSummary("Notificare: propunere pentru ștergere a fișierului [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
				usertalkpage.setCreateOption('recreate');
				switch (Twinkle.getPref('xfdWatchUser')) {
					case 'yes':
						usertalkpage.setWatchlist(true);
						break;
					case 'no':
						usertalkpage.setWatchlistFromPreferences(false);
						break;
					default:
						usertalkpage.setWatchlistFromPreferences(true);
						break;
				}
				usertalkpage.setFollowRedirect(true);
				usertalkpage.append();
			}
		},
		taggingImage: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{ffd|log=" + params.date + "}}\n" + text);
			pageobj.setEditSummary("Nominated for deletion at [[" + params.logpage + "#" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');  // it might be possible for a file to exist without a description page
			pageobj.save();
		},
		todaysList: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			// add date header if the log is found to be empty (a bot should do this automatically, but it sometimes breaks down)
			if (!pageobj.exists()) {
				text = "{{subst:Ffd log}}";
			}

			pageobj.setPageText(text + "\n{{subst:ffd2|1=" + mw.config.get('wgTitle') + "|Uploader=" + params.uploader + "|Reason=" + params.reason + "}} ~~~~");
			pageobj.setEditSummary("Adding [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		}
	},


	puf: {
		taggingImage: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{puf|help=off|log=" + params.date + "}}\n" + text);
			pageobj.setEditSummary("Listed at [[WP:PUF|possibly unfree files]]: [[" + params.logpage + "#" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');  // it might be possible for a file to exist without a description page
			pageobj.save();
		},
		todaysList: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText(text + "\n{{subst:puf2|image=" + mw.config.get('wgTitle') + "|reason=" + params.reason + "}} ~~~~");
			pageobj.setEditSummary("Adding [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		userNotification: function(pageobj) {
			var initialContrib = pageobj.getCreator();
			var usertalkpage = new Morebits.wiki.page('Discuție Utilizator:' + initialContrib, "Notific primul contribuitor (" + initialContrib + ")");
			var notifytext = "\n{{subst:idw-puf|1=" + mw.config.get('wgTitle') + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notificare: etichetare drept fișier posibil neliber a fișierului [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	},


	cfd: {
		taggingCategory: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			var added_data = "";
			var editsummary = "";
			switch( params.xfdcat ) {
			case 'cfd':
				added_data = "{{subst:cfd}}";
				editsummary = "Category being considered for deletion in accordance with [[WP:CDP|CDP]].";
				break;
			case 'cfm':
				added_data = "{{subst:cfm|" + params.target.replace('Category:','') + "}}";
				editsummary = "Category being considered for merging in accordance with [[WP:CDP|CDP]].";
				break;
			case 'cfr':
				added_data = "{{subst:cfr|" + params.target.replace('Category:','') + "}}";
				editsummary = "Category being considered for renaming in accordance with [[WP:CDP|CDP]].";
				break;
			case 'cfc':
				added_data = "{{subst:cfc|" + params.target + "}}";
				editsummary = "Category being considered for conversion to an article in accordance with [[WP:CDP|CDP]].";
				break;
			default:
				alert("twinklexfd in taggingCategory(): unknown CFD action");
				break;
			}

			pageobj.setPageText(added_data + "\n" + text);
			pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');  // since categories can be populated without an actual page at that title
			pageobj.save();
		},
		todaysList: function(pageobj) {
			var old_text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			var added_data = "";
			var editsummary = "";
			switch( params.xfdcat ) {
			case 'cfd':
				added_data = "{{subst:cfd2|1=" + mw.config.get('wgTitle') + "|text=" + params.reason + " ~~~~}}";
				editsummary = "Added delete nomination of [[:" + mw.config.get('wgPageName') + "]].";
				break;
			case 'cfm':
				added_data = "{{subst:cfm2|1=" + mw.config.get('wgTitle') + "|2=" + params.target + "|text=" + params.reason + " ~~~~}}";
				editsummary = "Added merge nomination of [[:" + mw.config.get('wgPageName') + "]].";
				break;
			case 'cfr':
				added_data = "{{subst:cfr2|1=" + mw.config.get('wgTitle') + "|2=" + params.target + "|text=" + params.reason + " ~~~~}}";
				editsummary = "Added rename nomination of [[:" + mw.config.get('wgPageName') + "]].";
				break;
			case 'cfc':
				added_data = "{{subst:cfc2|1=" + mw.config.get('wgTitle') + "|2=" + params.target + "|text=" + params.reason + " ~~~~}}";
				editsummary = "Added convert nomination of [[:" + mw.config.get('wgPageName') + "]].";
				break;
			default:
				alert("twinklexfd in todaysList: unknown CFD action");
				break;
			}

			text = old_text.replace( 'below this line -->', "below this line -->\n" + added_data );
			if( text === old_text ) {
				statelem.error( 'failed to find target spot for the discussion' );
				return;
			}

			pageobj.setPageText(text);
			pageobj.setEditSummary(editsummary + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		userNotification: function(pageobj) {
			var initialContrib = pageobj.getCreator();
			var params = pageobj.getCallbackParameters();
			var usertalkpage = new Morebits.wiki.page('Discuție Utilizator:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")");
			var notifytext = "\n{{subst:CFDNote|1=" + mw.config.get('wgPageName') + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notificare: punere în discuție a categoriei [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	},


	rfd: {
		// This is a callback from an API request, which gets the target of the redirect
		findTargetCallback: function(apiobj) {
			var xmlDoc = apiobj.responseXML;
			var target = $(xmlDoc).find('redirects r').first().attr('to');
			if( !target ) {
				apiobj.statelem.error( "This page is currently not a redirect, aborting" );
				return;
			}
			apiobj.params.target = target;
			Twinkle.xfd.callbacks.rfd.main(apiobj.params);
		},
		main: function(params) {
			var date = new Date();
			params.logpage = 'Wikipedia:Redirects for discussion/Log/' + date.getUTCFullYear() + ' ' + date.getUTCMonthName() + ' ' + date.getUTCDate();

			// Tagging redirect
			var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Adding deletion tag to redirect");
			wikipedia_page.setFollowRedirect(false);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.rfd.taggingRedirect);

			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = params.logpage;
			Morebits.wiki.actionCompleted.notice = "Nomination completed, now redirecting to today's log";

			// Adding discussion
			wikipedia_page = new Morebits.wiki.page(params.logpage, "Adding discussion to today's log");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.rfd.todaysList);

			// Notifying initial contributor
			if (params.usertalk) {
				var thispage = new Morebits.wiki.page(mw.config.get('wgPageName'));
				thispage.setCallbackParameters(params);
				thispage.lookupCreator(Twinkle.xfd.callbacks.rfd.userNotification);
			}
		},
		taggingRedirect: function(pageobj) {
			var text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();

			pageobj.setPageText("{{rfd}}\n" + text);
			pageobj.setEditSummary("Listed for discussion at [[" + params.logpage + "#" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchPage')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('nocreate');
			pageobj.save();
		},
		todaysList: function(pageobj) {
			var old_text = pageobj.getPageText();
			var params = pageobj.getCallbackParameters();
			var statelem = pageobj.getStatusElement();

			var text = old_text.replace( /(<\!-- Add new entries directly below this line -->)/, "$1\n{{subst:rfd2|redirect="+ mw.config.get('wgPageName') + "|target=" +
				params.target + "|text=" + Morebits.string.toUpperCaseFirstChar(params.reason) +"}} ~~~~\n" );
			if( text === old_text ) {
				statelem.error( 'failed to find target spot for the discussion' );
				return;
			}

			pageobj.setPageText(text);
			pageobj.setEditSummary("Adding [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			switch (Twinkle.getPref('xfdWatchDiscussion')) {
				case 'yes':
					pageobj.setWatchlist(true);
					break;
				case 'no':
					pageobj.setWatchlistFromPreferences(false);
					break;
				default:
					pageobj.setWatchlistFromPreferences(true);
					break;
			}
			pageobj.setCreateOption('recreate');
			pageobj.save();
			Twinkle.xfd.currentRationale = null;  // any errors from now on do not need to print the rationale, as it is safely saved on-wiki
		},
		userNotification: function(pageobj) {
			var initialContrib = pageobj.getCreator();
			var usertalkpage = new Morebits.wiki.page('User talk:' + initialContrib, "Notifying initial contributor (" + initialContrib + ")");
			var notifytext = "\n{{subst:RFDNote|1=" + mw.config.get('wgPageName') + "}} ~~~~";
			usertalkpage.setAppendText(notifytext);
			usertalkpage.setEditSummary("Notification: listing at [[WP:RFD|redirects for discussion]] of [[" + mw.config.get('wgPageName') + "]]." + Twinkle.getPref('summaryAd'));
			usertalkpage.setCreateOption('recreate');
			switch (Twinkle.getPref('xfdWatchUser')) {
				case 'yes':
					usertalkpage.setWatchlist(true);
					break;
				case 'no':
					usertalkpage.setWatchlistFromPreferences(false);
					break;
				default:
					usertalkpage.setWatchlistFromPreferences(true);
					break;
			}
			usertalkpage.setFollowRedirect(true);
			usertalkpage.append();
		}
	}
};



Twinkle.xfd.callback.evaluate = function(e) {
	mw.config.set('wgPageName', mw.config.get('wgPageName').replace(/_/g, ' '));  // for queen/king/whatever and country!

	var type =  e.target.category.value;
	var usertalk = e.target.notify.checked;
	var reason = e.target.xfdreason.value;
/*
	var xfdcat, puf, noinclude, tfdinline, notifyuserspace;
	if( type in {'afd':'','cfd':''} ) {
		xfdcat = e.target.xfdcat.value;
	}
	if( type === 'ffd' ) {
		puf = e.target.puf.checked;
	}
*/
	if( type in {'afd':'','mfd':''} ) {
		noinclude = e.target.noinclude.checked;
	}
/*
	if( type === 'tfd' ) {
		tfdinline = e.target.tfdinline.checked;
	}
	if( type === 'mfd' ) {
		notifyuserspace = e.target.notifyuserspace && e.target.notifyuserspace.checked;
	}
*/
	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( e.target );

	Twinkle.xfd.currentRationale = reason;
	Morebits.status.onError(Twinkle.xfd.printRationale);

	if( !type ) {
		Morebits.status.error( 'Eroare', 'acțiune nespecificată' );
		return;
	}

	var query, wikipedia_page, wikipedia_api, logpage, params;
	var date = new Date();
	switch( type ) {

	case 'afd': // AFD
		query = {
			'action': 'query',
			'list': 'allpages',
			'apprefix': 'Pagini de șters/' + mw.config.get('wgPageName'),
			'apnamespace': 4,
			'apfilterredir': 'nonredirects',
			'aplimit': Morebits.userIsInGroup( 'sysop' ) ? 5000 : 500
		};
		wikipedia_api = new Morebits.wiki.api( 'Etichetez articol cu eticheta de ștergere', query, Twinkle.xfd.callbacks.afd.main );
		wikipedia_api.params = { usertalk:usertalk, reason:reason, noinclude:noinclude };
		wikipedia_api.post();
		break;

	case 'ffd': // FFD
		var dateString = date.getUTCFullYear() + ' ' + date.getUTCMonthName() + ' ' + date.getUTCDate();
		logpage = 'Wikipedia:Files for deletion/' + dateString;
		params = { usertalk: usertalk, reason: reason, date: dateString, logpage: logpage };

		Morebits.wiki.addCheckpoint();
		if( puf ) {
			params.logpage = logpage = 'Wikipedia:Possibly unfree files/' + dateString;

			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = logpage;
			Morebits.wiki.actionCompleted.notice = "Nomination completed, now redirecting to today's list";

			// Tagging file
			wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Tagging file with PUF tag");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.puf.taggingImage);

			// Adding discussion
			wikipedia_page = new Morebits.wiki.page(params.logpage, "Adding discussion to today's list");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.puf.todaysList);

			// Notification to first contributor
			if (usertalk) {
				wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'));
				wikipedia_page.setCallbackParameters(params);
				wikipedia_page.lookupCreator(Twinkle.xfd.callbacks.puf.userNotification);
			}

			Morebits.wiki.removeCheckpoint();

		} else {
			// Updating data for the action completed event
			Morebits.wiki.actionCompleted.redirect = logpage;
			Morebits.wiki.actionCompleted.notice = "Nomination completed, now redirecting to the discussion page";

			// Tagging file
			wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Adding deletion tag to file page");
			wikipedia_page.setFollowRedirect(true);
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.load(Twinkle.xfd.callbacks.ffd.taggingImage);

			// Contributor specific edits
			wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'));
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.lookupCreator(Twinkle.xfd.callbacks.ffd.main);
		}
		Morebits.wiki.removeCheckpoint();
		break;

	case 'cfd':
		Morebits.wiki.addCheckpoint();

		var target;
		if( e.target.xfdtarget ) {
			target = e.target.xfdtarget.value.replace( /^\:?Categorie\:/, '' );
		} else {
			target = '';
		}

		logpage = 'Wikipedia:Categories for discussion/Log/' + date.getUTCFullYear() + ' ' + date.getUTCMonthName() + ' ' + date.getUTCDate();

		params = { reason: reason, xfdcat: xfdcat, target: target, logpage: logpage };

		// Updating data for the action completed event
		Morebits.wiki.actionCompleted.redirect = logpage;
		Morebits.wiki.actionCompleted.notice = "Nomination completed, now redirecting to today's log";

		// Tagging category
		wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), "Tagging category with deletion tag");
		wikipedia_page.setCallbackParameters(params);
		wikipedia_page.load(Twinkle.xfd.callbacks.cfd.taggingCategory);

		// Adding discussion to list
		wikipedia_page = new Morebits.wiki.page(logpage, "Adding discussion to today's list");
		//wikipedia_page.setPageSection(2);
			// pageSection has been disabled - the API seems to throw up with nonexistent edit conflicts
			// it can be turned on again once the problem is fixed, to save bandwidth
		//wikipedia_page.setFollowRedirect(true);
		wikipedia_page.setCallbackParameters(params);
		wikipedia_page.load(Twinkle.xfd.callbacks.cfd.todaysList);

		// Notification to first contributor
		if (usertalk) {
			wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'));
			wikipedia_page.setCallbackParameters(params);
			wikipedia_page.lookupCreator(Twinkle.xfd.callbacks.cfd.userNotification);
		}

		Morebits.wiki.removeCheckpoint();
		break;

	case 'rfd':
		params = { usertalk: usertalk, reason: reason };
		if (document.getElementById("softredirect")) {
			// For soft redirects, skip straight to the callback
			params.target = document.getElementById("softredirect").textContent.replace(/^\:+/, "");
			Twinkle.xfd.callbacks.rfd.main(params);
		} else {
			// Find current target of redirect
			query = {
				'action': 'query',
				'titles': mw.config.get('wgPageName'),
				'redirects': true
			};
			wikipedia_api = new Morebits.wiki.api( "Finding target of redirect", query, Twinkle.xfd.callbacks.rfd.findTargetCallback );
			wikipedia_api.params = params;
			wikipedia_api.post();
		}
		break;
	default:
		alert("twinklexfd: unknown XFD discussion venue");
		break;
	}
};


/**
 * General initialization code
 */

var scriptpathbefore = mw.config.get('wgServer') + mw.config.get('wgScript') + "?title=";
var scriptpathafter = "&action=raw&ctype=text/javascript&happy=yes";

// retrieve the user's Twinkle preferences
$.ajax({
	url: scriptpathbefore + "Utilizator:" + encodeURIComponent(mw.config.get('wgUserName')) + "/twinkleoptions.js" + scriptpathafter,
	dataType: 'text',
	error: function(){ mw.notify("N-am putut încărca twinkleoptions.js"); },
	success: function(optionsText){

		//quick pass if user has no options
		if ( optionsText === "/* Empty */" ) {
			return;
		}

		//twinkle options are basically a JSON object with some comments. Strip those:
		optionsText = optionsText.replace(/(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, "");

		//first version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.
		if (optionsText.lastIndexOf("window.Twinkle.prefs = ", 0) === 0) {
			optionsText = optionsText.replace(/(?:^window.Twinkle.prefs = |;\n*$)/g, "");
		}

		try {
			var options = JSON.parse(optionsText);

			// Assuming that our options evolve, we will want to transform older versions:
			//if (options.optionsVersion === undefined) {
			// ...
			// options.optionsVersion = 1;
			//}
			//if (options.optionsVersion === 1) {
			// ...
			// options.optionsVersion = 2;
			//}
			// At the same time, twinkleconfig.js needs to be adapted to write a higher version number into the options.

			Twinkle.prefs = options;
		}
		catch (e) {
			mw.notify("Nu am putut încărca twinkleoptions.js");
		}
	},
	complete: function(){
		$( Twinkle.load );
	}
});

// Developers: you can import custom Twinkle modules here
// for example, mw.loader.load(scriptpathbefore + "User:UncleDouggie/morebits-test.js" + scriptpathafter);

Twinkle.load = function(){
	// Don't activate on special pages other than "Contributions" so that they load faster, especially the watchlist.
	// Also, Twinkle is incompatible with Internet Explorer versions 8 or lower, so don't load there either.
	if ( (mw.config.get('wgNamespaceNumber') === -1 && mw.config.get('wgCanonicalSpecialPageName') !== "Contributions") || 
		($.client.profile().name === 'msie' && $.client.profile().versionBase < 9) ) {
		return;
	}

	// load the modules in the order that the tabs should appears
	// user/user talk-related
	mw.loader.load("mediawiki.util");
	mw.loader.load("jquery.ui");
	mw.loader.load("jquery.tipsy");
	//Twinkle.arv();
	Twinkle.warn();
	Twinkle.welcome();
	Twinkle.shared();
	Twinkle.talkback();
	// deletion
	Twinkle.speedy();
	Twinkle.xfd();
	Twinkle.image();
	// maintenance
	//Twinkle.protect();
	Twinkle.tag();
	// misc. ones last
	Twinkle.diff();
	Twinkle.unlink();
	Twinkle.config.init();
	Twinkle.fluff.init();
	if (Morebits.userIsInGroup('sysop')) {
		Twinkle.closer();
		//Twinkle.delimages();
		//Twinkle.batchdelete();
		//Twinkle.batchprotect();
		//Twinkle.imagetraverse();
		//Twinkle.batchundelete();
	}
	// run the initialization callbacks for any custom modules
	$(Twinkle.initCallbacks).each(function(k, v) { v(); });
	Twinkle.addInitCallback = function(func) { func(); };

	// increates text size in Twinkle dialogs bigger, if so configured
	if (Twinkle.getPref("dialogLargeFont")) {
		mw.util.addCSS(".morebits-dialog-content, .morebits-dialog-footerlinks { font-size: 100% !important; } " +
			".morebits-dialog input, .morebits-dialog select, .morebits-dialog-content button { font-size: inherit !important; }");
	}
};

} ( window, document, jQuery )); // End wrap with anonymous function
// </nowiki>