User:Darkbitlike/global.js

importArticles({   type: 'script',    articles: [        'u:dev:MediaWiki:View Source/code.js',        'u:dev:MediaWiki:ViewRemoved/code.js',        'u:dev:MediaWiki:RevealAnonIP/usercode.js',        'u:dev:MediaWiki:LastEdited/code.js',        'u:dev:MediaWiki:UnhideUserMasthead/code.js',        'u:dev:MediaWiki:Discussions Delete All/code.js',        // Tools        'u:dev:MediaWiki:RecentChangesMultiple/code.2.js',        'u:dev:MediaWiki:GlobalEditcount/code.js',        'u:dev:MediaWiki:UserAndIPTools.js',        'u:dev:WHAM/code.js',        'u:dev:MediaWiki:RollbackSpamUserContribs/code.js',        'u:dev:MediaWiki:UserActivityTab/code.js',        'u:dev:MediaWiki:DisableCode/code.js',    ] });

if (wgPageName == 'Special:Imagelist') { addOnloadHook(imagelistTools); } function imagelistTools { addPortletLink('p-cactions', 'javascript:showFLimages(0)', 'Show images (full)', 'ca-showim0', 'loads the images in a full sized image tag'); addPortletLink('p-cactions', 'javascript:showFLimages(1)', 'Show images (small)', 'ca-showim1', 'loads the images in a 200x200 image tag'); addPortletLink('p-cactions', 'javascript:filelistprune', 'Desc links only', 'ca-prune', 'turns the whole page into just a list of links'); } function showFLimages(full) { var links = document.getElementById('bodyContent').getElementsByTagName('a'); var img; for (var i = 0; i < links.length; i++) { if (links[i].firstChild.nodeValue == 'file') { links[i].firstChild.nodeValue = ''; links[i].parentNode.setAttribute('class', 'plainlinks'); img = document.createElement('img'); img.setAttribute('src', links[i].href); if (full == 0) { img.setAttribute('style', 'border:2px outset blue;'); } else { img.setAttribute('style', 'width:200px;height:200px;border:2px outset blue;'); }           links[i].appendChild(img); }   }    document.getElementById('ca-showim0').style.display = 'none'; document.getElementById('ca-showim1').style.display = 'none'; } function filelistprune { var descs = getElementsByClassName(document, 'td', 'TablePager_col_img_name'); var dlist = ' '; for (var i = 0; i < descs.length; i++) { dlist += '' + descs[i].firstChild.title + '\n'; }   dlist += ' \n'; document.getElementById('bodyContent').innerHTML = dlist; document.getElementById('ca-prune').style.display = 'none'; } $(function {   if (mw.config.get('wgNamespaceNumber') == 6) {        $('#WikiaPageHeader').append(' ');        if ($('#ca-undelete').length) {            $('#WikiaPageHeader').append('Undelete | ');        }        $('#WikiaPageHeader').append('Log');        mw.util.addPortletLink('p-cactions', mw.util.wikiGetlink( 'Special:Log?page=' + mw.config.get('wgPageName')), 'Log');    } });

// ***************************************************************** // Load various external scripts // ***************************************************************** // importScriptPage('User:Sannse/forumtools.js', 'community'); // importScriptPage('User:Splarka/contribtools.js', 'community'); // importScriptPage('FastDelete/code.js', 'dev'); /** * Ajax Fast Delete * * @author Splarka * @author Uberfuzzy * @author Grunny * * @version 2.3 */ /*global jQuery, mediaWiki */ "use strict"; window.dev = window.dev || {}; // Don't load twice... if (window.dev.ajaxFastDelete !== undefined) { return false; }   var conf = mw.config.get([            'wgNamespaceNumber',            'wgPageName',            'skin'        ]), self = { version: '2.3', init: function { if (conf.wgNamespaceNumber === -1 || !window.fdButtons || !$('#ca-delete').length) { return; }               var deleteButtons = ''; switch (conf.skin) { case 'uncyclopedia': case 'wowwiki': case 'monobook': deleteButtons = window.fdButtons.map(function (b) {                           var sum = b.summary;                            return '' + b.label + '';                        }).join(''); $('#p-cactions > .pBody > ul').append(deleteButtons); break; case 'oasis': case 'wikia': var $profile = $('.UserProfileActionButton'); deleteButtons = window.fdButtons.map(function (b) {                           var sum = b.summary;                            return '' + b.label + '';                        }).join(' '); if ($profile.exists) { $profile.append(deleteButtons); } else if ($('.page-header__subtitle-blog-post').exists) { $('.page-header__subtitle-blog-post').append(deleteButtons); $('.page-header__blog-post-details').css('margin-right', '5px'); } else { $('.page-header__title').append(deleteButtons); mw.util.addCSS('a[data-id="fastdelete"]:nth-child(1){margin-left:5px}'); }                       break; }               if ($('a[data-id="fastdelete"]').length) { $('a[data-id="fastdelete"]').click(function {                       self.deletePage($(this).attr('data-summary'));                    }); }               mw.hook('fastdelete.init').fire(deleteButtons); },           deletePage: function (deleteReason) { (new mw.Api) .post({                       action: 'delete',                        title: conf.wgPageName,                        reason: deleteReason,                        token: mw.user.tokens.get('editToken')                    }) .done(function (res) {                       location.reload;                    }); }       };    window.dev.ajaxFastDelete = self; mw.loader.using(['mediawiki.util', 'mediawiki.api'], function {        $(self.init);    }); }(window, jQuery, mediaWiki)); // ***************************************************************** // Custom automatic delete buttons // ***************************************************************** // Adds customizable one-click deletion buttons to any deletable page. // Requires w:User:Splarka/fastdelete.js in appendScript; var fdButtons = []; fdButtons[fdButtons.length] = {   'summary': '* Violation of Fandom\'s Terms of Use ',    'label': 'ToU-Violation' }; fdButtons[fdButtons.length] = {    'summary': 'Requested deletion',    'label': 'request-deletion' }; fdButtons[fdButtons.length] = {    'summary': 'Spam ',    'label': 'Spam' }; fdButtons[fdButtons.length] = {    'summary': 'Removed due to DMCA claim',    'label': 'DMCA' }; fdButtons[fdButtons.length] = {    'summary': 'Housekeeping',    'label': 'house-keep' }; fdButtons[fdButtons.length] = {    'summary': 'Unused video', 'label': 'unused-vid' }; fdButtons[fdButtons.length] = { 'summary': 'Plagarism', 'label': 'plagarism' }; // end Custom automatic delete buttons if (wgNamespaceNumber != -1) addOnloadHook(function {   addPortletLink('p-cactions', '/wiki/Special:Prefixindex/' + escape(wgPageName), 'Subpages', 'ca-subpages', 'Show subages of ' + wgPageName); }); //gear fixer (from uberfuzzy) $('a[data-name="customize"]').html(function {   return $(this).parent.find('img').detach; }); //Thingy from Sactage to fix lookupuser $(function {   if (mw.config.get('wgCanonicalSpecialPageName') === 'Contributions' && mw.config.get('wgCityId') != '177') {        var target = mw.util.getParamValue('target') || mw.config.get('wgPageName').split('/', 2)[1] || null;        if (!target) {            return;        }        $('#contentSub > a:nth-child(9)').attr('href', 'http://community.wikia.com/wiki/Special:LookupUser?target=' + encodeURIComponent(target));    } }); /** * @author: Flightmare (http://elderscrolls.wikia.com/wiki/User:Flightmare) * @version: 1.0 * @license: CC-BY-SA 3.0 * @description: Imports biography from discussions to ns:2 if no profile page is present. */ //replace redlink placeholder with discussions bio. function addDProfile(text) { var content = document.getElementsByClassName("noarticletext")[0]; content.innerHTML = text.replace(/(?:\r\n|\r|\n)/g, ' '); } function getUserBio(userId) { var request = new XMLHttpRequest; request.onreadystatechange = function { if (request.readyState == 4 && request.status == 200) { var arr = JSON.parse(request.responseText); if (Boolean(arr.value)) { //Only continue if there is an actual bio written. addDProfile(arr.value); }       }    };    request.open("GET", "https://services.wikia.com/user-attribute/user/" + userId + "/attr/bio", true); request.send; } //Is there a better way to get the user id? function getUserIdByName(username) { var request = new XMLHttpRequest; request.onreadystatechange = function { if (request.readyState == 4 && request.status == 200) { var arr = JSON.parse(request.responseText); userId = arr["query"]["allusers"][0].id; if (Boolean(userId)) { getUserBio(userId); }       }    };    request.open("GET", "/api.php?action=query&list=allusers&aufrom=" + username + "&format=json&aulimit=1", true); request.send; } $(function createDProfiles {   if (wgNamespaceNumber == 2) {        //Test if profile page exists (we want this to 404)        var request = new XMLHttpRequest;        request.onreadystatechange = function {            if (request.readyState == 4 && request.status == 404) {                var username = wgPageName.substring(wgCanonicalNamespace.length + 1); //This should be i18n-safe.                getUserIdByName(username);            }        };        request.open("GET", "/wiki/" + wgPageName, true);        request.send;    } }); // Adds log link to deleted images header $(function {   if ($('#mw-imagepage-nofile').length) {        $('View logs for this page ').insertAfter('.page-header__title');    } });
 * (function (window, $, mw, undefined) {

// Fire an Vandalism Reverter

mw.loader.using('mediawiki.api', function {	//Exit if normal rollback links are present	if ($('.mw-rollback-link').length || window.RollbackWikiDisable) return;	var conf = mw.config.get([ 'wgAction', 'wgCanonicalSpecialPageName', 'wgContentLanguage', 'wgPageName', 'wgUserLanguage' ]),	i18n = {		en: {			rollback: "rollback",			description: "&quot;Rollback&quot; reverts edit(s) to this page of the last contributor in one click",			summary: "Reverted edits by $1 (talk) to last version by $2 (script)",			summaryShort: "Reverted edits by $1 (script)",			editConflict: "Unable to rollback (edit conflict)",			contentFail: "Unable to rollback (failed to get page content)",			singleEditor: "Unable to rollback (no different editor found)",			revisionFail: "Unable to rollback (failed to get revisions)",			editFail: "Unable to rollback (failed to publish edit)",			success: "Rollback successful"		},		ru: {			rollback: "rollback",			description: "&quot;Rollback&quot; reverts edit(s) to this page of the last contributor in one click",			summary: "Откат правок без статуса откатчика (скрипт)", summaryShort: "Reverted edits by $1 (script)", editConflict: "Произошёл конфликт правок", contentFail: "Произошла ошибка", singleEditor: "Произошла ошибка", revisionFail: "Произошла ошибка", editFail: "Произошла ошибка", success: "Откат совершен" },		fr: { rollback: "révoquer", description: "&quot;Rollback&quot; révoque la/les modification(s) du dernier contributeur de cette page en un clic", summary: "Révoqué les modifications par $1 (talk) à la dernière version par $2 (script)", summaryShort: "Révoqué les modifications par $1 (script)", editConflict: "Impossible de révoquer (conflit de modifications)", contentFail: "Impossible de révoquer (échec de l'obtention du contenu de la page)", singleEditor: "Impossible de révoquer (aucun éditeur différent trouvé)", revisionFail: "Impossible de révoquer (échec de l'obtention des révisions)", editFail: "Impossible de révoquer (échec de la publication de la modification)", success: "Révocation(s) réussie(s) !" }	};	i18n = i18n[conf.wgContentLanguage] || i18n[conf.wgContentLanguage.split('-')[0]] || i18n[conf.wgUserLanguage] || i18n[conf.wgUserLanguage.split('-')[0]] || i18n.en; //History if (conf.wgAction == "history" && $('#pagehistory li').length > 1) $('#pagehistory li:first .mw-history-undo a').before(' ' + i18n.rollback + '</a> | '); //Contributions else if (conf.wgCanonicalSpecialPageName == "Contributions") { $('#mw-content-text ul').find('li').each(function {			if ($(this).find('.mw-uctop').length)				$(this).append(' [' + i18n.rollback + '</a>] ');		}); }	//Diffs else if (($.getUrlVar('diff') || $.getUrlVar('oldid')) && $('#differences-nextlink').length === 0) $('.mw-usertoollinks:last').after('   [' + i18n.rollback + '</a>] '); else return; conf.API = new mw.Api; conf.token = mw.user.tokens.values.editToken; mw.util.addCSS('.mw-custom-rollback-link a { cursor: pointer; }'); $('.mw-custom-rollback-link a').click(function {		getRevisionIdAndContent($(this).data('id'),$(this).data('user').replace(/_/g, " "));		$(this).parent.remove;	}); function getRevisionIdAndContent(title,target) { conf.API.get({		action: 'query',		prop: 'revisions',		titles: title,		rvprop: 'user|ids',		rvlimit: 500,		cb: new Date.getTime		}) .done(function(d) {			if (!d.error) {				var revisions;				for (var i in d.query.pages) {					revisions = d.query.pages[i].revisions;				}				//Don't rollback if the page has been edited by somebody else				if (target != revisions[0].user) {					outputError(i18n.editConflict);					return;				}				var lastUser,				revId;				for (var i in revisions) {					if (revisions[i].user != target) {						lastUser = revisions[i].user; //remember last author						revId = revisions[i].revid; //get revision to revert to						break;					}				}				if (lastUser) {					conf.API.get({ action: 'query', prop: 'revisions', rvprop: 'content', revids: revId, cb: new Date.getTime })					.done(function(d) { if (!d.error) { var content = ""; //can be no content on page for (var i in d.query.pages) { if (d.query.pages[i].revisions) content = d.query.pages[i].revisions[0]["*"]; }							performRollback(title,content,target,lastUser); }						else outputError(i18n.contentFail + ': ' + d.error.code); })					.fail(function { outputError(i18n.contentFail); });				}				else					outputError(i18n.singleEditor);			}			else				outputError(i18n.revisionFail + ': ' + d.error.code);		}) .fail(function {			outputError(i18n.revisionFail);		}); }	function performRollback(page,text,user,user2) { var summary = i18n.summary.replace(/\$1/g,user).replace(/\$2/g,user2); if (summary.length > 150) summary = i18n.summaryShort.replace('$1',user); conf.API.post({		action: 'edit',		title: page,		text: text,		summary: summary,		minor: true,		token: conf.token		}) .done(function(d) {			if (!d.error) {				new BannerNotification(i18n.success,'confirm').show;							}			else				outputError(i18n.editFail + ': ' + d.error.code);		}) .fail(function {			outputError(i18n.editFail);		}); }	function outputError(text) { new BannerNotification(text,'error').show; } });

// Vanguard Tools

/** *  * @module                  VanguardTools * @description            Accelerates Vanguard migration workflow. * @author                 Speedit * @version                1.2.1 * @license                CC-BY-SA 3.0 * */ require(['wikia.window', 'jquery', 'mw', 'wikia.nirvana', 'ext.wikia.design-system.loading-spinner'], function (window, $, mw, nirvana, Spinner) {    'use strict';    // Script variables and double run protection.    if (window.vanguardToolsLoaded) {        return;    }    window.vanguardToolsLoaded = true;    var VAN = {};    // MediaWiki variables.    VAN.mw = mw.config.get([ 'wgMessages', 'wgDBname', 'wgCanonicalNamespace', 'wgCanonicalSpecialPageName', 'wgTitle', 'wgAction', 'wgArticleId', 'wgArticlePath', 'wgLoadScript', 'wgUserGroups' ]);   // User parrot status.    VAN.parrot = VAN.mw.wgUserGroups.some(function(ug) { return ['user'].indexOf(ug) > -1; });   // Script configuration.    VAN.config = window.vanguardToolsConfig || {        state: true,        modules: [],        redirect: true,        nav: true,        template: true,        showdraft: true,        insights: true,        adminalert: true    };    if (VAN.config.modules && !$.isArray(VAN.config.modules)) {        delete VAN.config.modules;    }    // Design system integration.    VAN.wds = {        // Library handler.        handler: function(wds) {            // Cache our design system utils.            $.extend(VAN.wds, wds);            // Asset loading done.            VAN.wds.$loaded.resolve;        },        // Asset loading event.        $loaded: $.Deferred    };    // I18n implementation.    VAN.i18n = {        // Message & utility loader.        handler: function(i18no) {            i18no.loadMessages('VanguardTools').done(VAN.i18n.store);        }, // Message data handler. store: function(i18n) { // Cache our msg data, utils $.extend(VAN.i18n, i18n); // Message loading done. VAN.i18n.$loaded.resolve; },       // I18n event. $loaded: $.Deferred };   // Main script VAN.init = function { if (!VAN.parrot || !VAN.config.state) { return; } // Dispatch dependency handlers. mw.hook('dev.i18n').add(VAN.i18n.handler); mw.hook('dev.wds').add(VAN.wds.handler); // Module activator. $.when(VAN.i18n.$loaded, VAN.wds.$loaded).then(function {           // Run all modules by default.            VAN.config.modules = VAN.config.modules.length > 0 ?                VAN.config.modules :                VAN.modules;            // Validation for modules.            $.each(VAN.config.modules, function(i, m) { if (VAN.modules.indexOf(m) === -1) { VAN.modules.splice(i, 1); }           });            // Initialise all configured modules.            $.each(VAN.config.modules, function(i, m) { VAN[m].init; });           // Post-execution event            $.when.apply(null, VAN.config.modules.map(function(m) {                return VAN[m].$executed;            })).then(function { // Loaded class. $(document.body).addClass('van-is-loaded'); // Fire hook. mw.hook('dev.van').fire(VAN); });       });        // Import dependencies. importArticle({ type: 'script', article: 'u:dev:I18n-js/code.js' }); importArticle({ type: 'script', article: 'u:dev:WDSIcons/code.js' }); importArticle({ type: 'script', article: 'u:dev:ProtectionIcons.js' }); };   // Redirect module for S:IB. VAN.redirect = { init: function { if (               VAN.config.redirect !== true ||                VAN.mw.wgCanonicalSpecialPageName !== 'InfoboxBuilder' ||                VAN.mw.wgTitle.indexOf('/') === -1            ) { VAN.redirect.$executed.resolve; return; }           // Template existence check. VAN.redirect.template = mw.util.wikiUrlencode(VAN.mw.wgTitle.match(/\/([\s\S]+)$/)[1]); nirvana.getJson('PortableInfoboxBuilderController', 'getTemplateExists', {               title: VAN.redirect.template            }, VAN.redirect.builder); },       // Redirect notification. builder: function(t) { if (t.exists) { VAN.redirect.execute; return; }           if (navigator.serviceWorker) { // Create notification service worker. VAN.redirect.worker = navigator.serviceWorker.register(new mw.Uri(VAN.mw.wgLoadScript).extend({ 'debug': mw.config.get('debug'), 'lang': mw.config.get('wgUserLanguage'), 'mode': 'articles', 'skin': mw.config.get('skin'), 'missingCallback': 'importNotifications.importArticleMissing', 'articles': mw.util.wikiUrlencode('u:dev:VanguardTools/service-worker.js'), 'reviewed': mw.config.get('wgReviewedScriptsTimestamp'), 'only': 'scripts' }).getRelativePath); // Create two-way message channel. VAN.redirect.mch = new MessageChannel; VAN.redirect.mch.port1.onmessage = VAN.redirect.handler; // Post notification data to worker. Notification.requestPermission.then(VAN.redirect.post); }       },        post: function(r) { if (r !== 'granted') { return; }           navigator.serviceWorker.controller.postMessage({                command: 'van_send_notif',                i18n: {                    cancel: VAN.mw.wgMessages['cancel'],                    ok: VAN.mw.wgMessages['ok'],                    source: VAN.i18n.msg('sourceredirect').plain                }            }, [VAN.redirect.mch.port2]); },       // Infobox builder template creation. handler: function(e) { if (e.data.command !== 'van_create_infobox') { return; } // Spinner code. VAN.redirect.spinner = $(' ').css({                   background:                        $(document.body).css('background-color')                            .replace('rgb','rgba').replace(')', ', 0.5)'),                    position: 'fixed',                    height: '100%',                    width: '100%',                    left: '0',                    top: '0',                    'z-index': '1000000000'                }).html(function {                    return new Spinner(38, 2).html                        .replace('wds-block', 'wds-spinner__block')                        .replace('wds-path', 'wds-spinner__stroke');                }).appendTo(document.body); // Create infobox. nirvana.sendRequest({               controller: 'PortableInfoboxBuilderController',                method: 'publish',                data: {                    data: VAN.redirect.infobox,                    title: VAN.redirect.template,                    oldTitle: VAN.redirect.template,                    token: mw.user.tokens.get('editToken')                },                callback: VAN.redirect.callback            }); },       // Infobox data object. infobox: function { return JSON.stringify({               "data": [                    {                        "data": { "defaultValue": "" },                        "source": "name",                        "type": "title"                    },                    {                        "data": { "caption": { "source": "caption" }},                        "source": "image",                        "type": "image"                    },                    {                        "data": VAN.i18n.msg('piheader').plain,                        "collapsible": false,                        "type": "section-header"                    },                    {                        "data": {"label": VAN.i18n.msg('pitype').plain },                        "source": "type",                        "type": "row",                        "sourceFrozen": false                    }                ]            }); },       // Infobox builder redirection. callback: function(d) { VAN.redirect.spinner.remove; if (d.success) { VAN.redirect.execute; } else { VAN.redirect.handler; }       },        execute: function { var uri = new mw.Uri(               mw.util.getUrl('Template:' + VAN.redirect.template)            ); uri.extend({               action: 'edit',                useeditor: 'source'            }); window.location.href = uri.toString; VAN.redirect.$executed.resolve; },       $executed: $.Deferred };   // Global navigation links module. VAN.nav = { init: function { if (VAN.config.nav !== true) { VAN.nav.$executed.resolve; return; }           var $l = $('<ul>').addClass('wds-list wds-is-linked'); $.each(VAN.nav.uri, function(l, t) {               $l.append( $('').append(                       $('', { 'href': (function(t) {                               var p = VAN.mw.wgArticlePath.replace('$1', t);                                return p;                            }(t)), text: VAN.i18n.msg(l).plain })                   )                );            });            // Icon and dropdown generation. var icon = VAN.wds.icon('menu-control-tiny', {               'class': 'wds-dropdown-chevron'            }); var $c = VAN.nav.dropdown($l, icon); // Append to menu $('.wds-global-navigation__user-menu') // Prevent scrollable dropdown. .children('.wds-dropdown__content') .addClass('wds-is-not-scrollable') // Insert dropdown. .find('.wds-list > li > a[data-tracking-label="account.profile"]').parent.after($c); VAN.nav.$executed.resolve; },       // Create dropdown. dropdown: function($l, icon) { return $('', {               'id': 'van-tools-dropdown',                'class': 'wds-dropdown-level-2'            }).append(                $('', { 'href': mw.util.getUrl(VAN.nav.uri.insights), 'target': '_blank', 'rel': 'noopener noreferrer', 'class': [ 'wds-dropdown-level-2__toggle', 'van-tools-link' ].join(' ') }).append( $(' ', {                       text: VAN.i18n.msg('tools').plain                    }), icon ),               $(' ', {                    'class': [ 'wds-dropdown-level-2__content', 'wds-is-not-scrollable', 'van-tools-menu' ].join(' ') }).append($l)           ); },       // Global navigation links. uri: { insights:       'Special:Insights/nonportableinfoboxes', infoboxes:      'Special:Templates?type=infobox', templates:      'Special:Templates', sitecss:        'Special:CSS', personalcss:    'Special:MyPage/common.css', themescss:      'MediaWiki:Themes.css?action=edit', admins:         'Special:ListUsers/sysop,bureaucrat,rollback,threadmoderator,content-moderator,chatmoderator', wikifeatures:   'Special:WikiFeatures' },       $executed: $.Deferred };   // Template reclassification hotkey module. VAN.template = { init: function { if (               VAN.config.template !== true ||                VAN.mw.wgCanonicalNamespace !== 'Template' ||                VAN.mw.wgAction !== 'view'            ) { VAN.template.$executed.resolve; return; }           var $popout = $(' ', {                'class': 'van-popout color1'            }).hide.append(                $('<b>', { text: VAN.i18n.msg('templatetypeguide').plain }),               $('<ul>')            ); $popout.appendTo(document.body); nirvana.getJson(               'TemplateClassification',                'getTemplateClassificationEditForm',                function(d) {                    // Extract labels.                    d.templateTypes.forEach(function(dt) { VAN.template.labels[dt.type] = dt.name; });                   // Ready the popout.                    $popout.children('ul').append( $.map(VAN.template.types, function(o, k) {                           return $('').append( $(' ', {                                   text: o.key                                }), $(' ', {                                   text: VAN.template.labels[o.type]                                }) );                       })                    );                    $popout.show;                    // Delegate keyboard handler.                    $(document).keyup(VAN.template.shortcut);                    VAN.template.$executed.resolve;                }            ); },       // Shortcut keys. shortcut: function(e) { if (               !VAN.template.types.hasOwnProperty(e.which) ||                !e.altKey            ) { return; }           VAN.template.type = VAN.template.types[e.which].type, VAN.template.label = VAN.template.labels[VAN.template.type]; nirvana.postJson(               'TemplateClassificationApi',                'classifyTemplate',                {                    pageId: mw.config.get('wgArticleId'),                    type: VAN.template.type,                    editToken: mw.user.tokens.values.editToken                },                VAN.template.success            ); },       // Callback for TemplateClassification controller. success: function { $('.template-classification-type-label').text(VAN.template.label); var message = VAN.i18n.msg('templatetypechange', VAN.template.label).plain; notification = new BannerNotification(message, 'confirm'); notification.show; },       // Template type map for keyboard shortkeys. types: { 223: { key: '`', type: 'infobox' }, 49: { key: '1', type: 'quote' }, 50: { key: '2', type: 'navbox'}, 51: { key: '3', type: 'notice' }, 52: { key: '4', type: 'context-link' }, 53: { key: '5', type: 'infoicon' }, 54: { key: '6', type: 'scrollbox' }, 55: { key: '7', type: 'references' }, 56: { key: '8', type: 'media' }, 57: { key: '9', type: 'data' }, 48: { key: '0', type: 'design' }, 189: { key: '-', type: 'navigation' }, 187: { key: '=', type: 'nonarticle' } },       labels: {}, $executed: $.Deferred };   // S:I/NPI utility extension. VAN.insights = { // Module initialiser. init: function { if (               VAN.config.insights !== true ||                !$('.insights-nav-item.insights-icon-nonportableinfoboxes.active')                    .find('.insights-red-dot').exists            ) { VAN.insights.$executed.resolve; return; }           // Data lists. VAN.insights.list = {}; var chunks = []; [].slice.call($('.insights-list-item-title')).map(function(e, i) {               // Template name.                var t = e.innerText;                $(e).closest('.insights-list-item')                    .attr('data-template', t);                // API data.                VAN.insights.list[t] = {};                ( chunks[Math.floor(i / 50)] = chunks[Math.floor(i / 50)] || []               )[i % 50] = t;            }); VAN.insights.api = new mw.Api; chunks.forEach(function(c) {               VAN.insights.api.get({ 'action': 'query', 'prop': 'info', 'inprop': 'protection', 'titles': c.join('|') }).done(VAN.insights.handler);           }); },       // Template list list: {}, // API handler. handler: function(d) { $.each(d.query.pages, function(id, data) {               VAN.insights.list[data.title].protection =                    data.protection.filter(function(obj) { return (obj.type === 'edit'); }).length > 0;           }); if (Object.keys(VAN.insights.list).every(function(t) { return VAN.insights.list[t].hasOwnProperty('protection'); })) {               VAN.insights.ui; }       },        // Interface configuration map for actions. map: { 'viewdraft': { icon: 'eye-small' },           'conversion': { icon: 'gear-small' },           'rawcode': { icon: 'article-small', query: { action: 'raw', ctype: 'text/css' // Firefox fix. }           },            'protected': { icon: 'lock-small', query: { action: 'history' }           },            'unprotected': { icon: 'unlock-small', query: { action: 'history' }              }        },        // UI modification. ui: function { // Add page header class (hack for button colors). $('.insights-content').addClass('page-header'); // Button map for WDS icon addition. $('.insights-list-cell-altaction .wikia-button').each(function {               var $b = $(this),                    t = $(this).closest('.insights-list-item')                        .attr('data-template');                VAN.insights.list[t].$toolbar =                    $(' ', { 'class': [ 'wds-button-group', 'van-action-button-group' ].join(' ') }).insertBefore($b).append($b);               // Class addition.                $b                    .removeAttr('class')                    .addClass([ 'wds-button', 'wds-is-squished' ].join(' '))                   .addClass(function(i, c) { if ($b.attr('href').indexOf('action=edit') > -1) { return [ 'van-action-button', 'van-is-conversion' ].join(' '); } else { return [ 'wds-is-secondary', 'van-action-button', 'van-is-viewdraft' ].join(' '); }                   }).html(function(i, html) { return ' ' + mw.html.escape(html) + ' '; });               // List buttons.                VAN.insights.list[t].$buttons = [$b];                // Generate toolbar.                VAN.insights.tbr(t);            }); },       // Template toolbar generator. tbr: function(t) { var b = { 'unprotected': false, 'protected': true },               $t = VAN.insights.list[t].$toolbar; // Button creation. $.each(VAN.insights.map, function(l, c) {               // Prevent duplication.                if ( !['conversion', 'viewdraft'].some(function(s) {                       return l === s;                    }) && (                       Object.keys(b).indexOf(l) === -1 ||                        VAN.insights.list[t].protection === b[l]                    ) ) {                   // Button element.                    var $b = $('', { 'href': (function {                               var uri = new mw.Uri(mw.util.getUrl(t));                                // Add query                                if (c.query) {                                    uri.extend(c.query);                                }                                return uri.toString;                            }), html: $(' ', {                               text: VAN.i18n.msg(l).plain                            }) })                       .addClass([ 'wds-button', 'wds-is-squished', 'wds-is-secondary', 'van-tools-button', 'van-is-' + l                       ].join(' '))                        .appendTo(VAN.insights.list[t].$toolbar);                    // Cache button.                    VAN.insights.list[t].$buttons.push($b);                }                // Icon addition.                $t.children('.van-is-' + l)                    .prepend(VAN.wds.icon(c.icon));            }); VAN.insights.$executed.resolve; },       $executed: $.Deferred };   // "You are editing this page without admin" alert. VAN.adminalert = { init: function { if (VAN.config.adminalert !== true) { VAN.adminalert.$executed.resolve; return; }           if (                !['dev', 'communitytest'].includes(VAN.mw.wgDBname) &&                VAN.mw.wgCanonicalNamespace === 'MediaWiki' &&                !/sysop/.test(VAN.mw.wgUserGroups)            ) { $('#ca-edit') .addClass('van-admin-alert') .attr('title', VAN.i18n.msg('adminalert').plain) .find('svg').before(VAN.wds.icon('alert-small').outerHTML); }           VAN.adminalert.$executed.resolve; },       $executed: $.Deferred };   // Replace the create draft button with a link to the page if it is already available. VAN.showdraft = { init: function { var draftDiv = $('section.templatedraft-module.module'); var draftAnchor = draftDiv.children('a'); var draftAnchorHref = draftAnchor.attr('href'); if (               VAN.config.showdraft !== true ||                VAN.mw.wgCanonicalNamespace !== 'Template' ||                VAN.mw.wgAction !== 'view' ||                draftDiv.length <= 0 ||                draftAnchor.length <= 0 ||                draftAnchorHref.indexOf('action=approvedraft') > 0            ) { VAN.showdraft.$executed.resolve; return; }           var draftUrl = draftAnchorHref.slice(0,draftAnchorHref.lastIndexOf('?')); $.ajax(draftUrl + '?action=raw').done(function {                draftDiv.children('h2').text(VAN.i18n.msg('showdraftheader').plain);                draftDiv.children('.templatedraft-module-subtitle').remove;                draftDiv.children('p').text(VAN.i18n.msg('showdraftbody').plain);                draftAnchor.attr('href', draftUrl);                draftAnchor.children('button').text(VAN.i18n.msg('showdraftbutton').plain);            }); VAN.showdraft.$executed.resolve; },       $executed: $.Deferred };   // Module registry. VAN.modules = Object.keys(VAN).filter(function(m) {       return ( typeof VAN[m] === 'object' && // class check VAN[m].init                  // initializer check );   });    // Import styling. importArticle({       type: 'style',        article: 'u:dev:MediaWiki:VanguardTools.css'    }); // Script initializer. mw.loader.using([       'mediawiki.util',        'mediawiki.api',        'jquery.tablesorter',        'ext.bannerNotifications'    ]).then(VAN.init); }); /** **/

/** * Mass Rename * @description Rename pages quickly. * @author Ozuzanna */ mw.loader.using('mediawiki.api', function {    if ( window.MassRenameLoaded || !/user/.test(mw.config.get('wgUserGroups').join) ) {       return;    }    window.MassRenameLoaded = true;    var i18n,        placement,        renameModal,        preloads = 3,        paused = false;    /**     * @method formHtml     * @description Creates the modal HTML     */    function formHtml  {        return $(' ', { 'class': 'WikiaForm' }).append( $(' ').append(               $(' ', { text: i18n.msg('instructions').plain }),               $(' ', {                    text: i18n.msg('instructions2').plain }),               $(' ', {                    'for': 'redirect-check', text: i18n.msg('redirect').plain }).append( $(' ', {                       type: 'checkbox',                        id: 'redirect-check'                    }) ),               $(' ', {                    id: 'text-rename', placeholder: 'old_name new_name' }),               $(' ', {                    id: 'text-error-output', text: i18n.msg('outputInitial').plain, append: ' ' })           )        ).prop('outerHTML');    }    /**     * @method preload     * @description Loads the hooks and I18n messages     */    function preload  {        if (--preloads === 0) {            placement = window.dev.placement.loader;            window.dev.i18n.loadMessages('MassRename').then(init);        }    }    /**     * @method init     * @description Initiates the script     * @param {String} i18nData - Variable for I18n-js     */    function init (i18nData) {        i18n = i18nData;        placement.script('MassRename');        $(placement.element('tools'))[placement.type('prepend')]( $('').append(               $('', { id: 't-mr', text: i18n.msg('title').plain, click: click })           )        );    }    /**     * @method click     * @description Opens the MassRename modal     */    function click  {        if (renameModal) {            renameModal.show;            return;        }        renameModal = new window.dev.modal.Modal({ content: formHtml, id: 'form-mass-rename', size: 'medium', title: i18n.msg('title').escape, buttons: [ {                   id: 'mr1-start', text: i18n.msg('initiate').escape, primary: true, event: 'start' },               {                    id: 'mr1-pause', text: i18n.msg('pause').escape, primary: true, event: 'pause', disabled: true },               {                    text: i18n.msg('close').escape, event: 'close' }           ],            events: { pause: pause, start: start }       });        renameModal.create;        renameModal.show;    }    /**     * @method pause     * @description Pauses the operation     */    function pause  {        paused = true;        document.getElementById('mr1-pause').setAttribute('disabled', );        document.getElementById('mr1-start').removeAttribute('disabled');    }    /**     * @method start     * @description Starts the operation     */    function start  {        paused = false;        document.getElementById('mr1-start').setAttribute('disabled', );        document.getElementById('mr1-pause').removeAttribute('disabled');        process;    }    /**     * @method process     * @description Analyzes the inputted data     */    function process  {        if (paused) {            return;        }        var txt = document.getElementById('text-rename'),            pages = txt.value.split('\n'), page = pages[0]; if (!page) { $('#text-error-output').append(               i18n.msg('finished').escape +                ' ' +                i18n.msg('nothingLeftToDo').escape +                ' '            ); pause; } else { rename(page); }       pages = pages.slice(1, pages.length); txt.value = pages.join('\n'); }   /**     * @method rename * @description Renames the page * @param {String} name - The rename data */   function rename (name) { if (name.split(' ').length !== 2) { $('#text-error-output').append(i18n.msg('invalidInput', name).escape + ' '); } else { var oldName = name.split(' ')[0], newName = name.split(' ')[1], config = { action: 'move', from: oldName.replace('_', ' '), to: newName.replace('_', ' '), noredirect: '', reason: window.massRenameSummary || i18n.inContentLang.msg('summary').plain, bot: true, token: mw.user.tokens.get('editToken') };           if (document.getElementById('redirect-check').checked) { delete config.noredirect; }           new mw.Api.post(config) .done(function (d) {               if (!d.error) {                    console.log(i18n.msg('renameDone', oldName, newName).plain);                } else {                    console.log(i18n.msg('renameFail', oldName, newName).escape + ': ' + d.error.code);                    $('#text-error-output').append(i18n.msg('renameFail', oldName, newName).escape + ': ' + d.error.code + ' ');                }            }) .fail(function {                console.log(i18n.msg('renameFail2', oldName, newName).plain);                $('#text-error-output').append(i18n.msg('renameFail2', oldName, newName).escape + ' ');            }); }       setTimeout(process, window.massRenameDelay || 1000); }   mw.hook('dev.i18n').add(preload); mw.hook('dev.modal').add(preload); mw.hook('dev.placement').add(preload); importArticles(       {            type: 'script',            articles: [                'u:dev:MediaWiki:I18n-js/code.js',                'u:dev:MediaWiki:Modal.js',                'u:dev:MediaWiki:Placement.js'            ]        },        {            type: 'style',            articles: ['u:dev:MediaWiki:MassRename.css']        }    ); });

/** * MassEdit/code.js * @file Adds/deletes/replaces content from pages/categories/namespaces * @author Eizen <dev.wikia.com/wiki/User_talk:Eizen> * @external "mediawiki.util" * @external "jQuery" * @external "wikia.ui.factory" * @external "wikia.window" * @external "I18n-js" * @external "mw" */ /*jslint browser, this:true */ /*global mw, jQuery, window, require, wk, ui */ require(["jquery", "mw", "wikia.window", "wikia.ui.factory"],       function (jQuery, mw, wk, ui) {    "use strict";    if (jQuery("#massEdit-li").exists || window.isMassEditLoaded) {        return;    }    window.isMassEditLoaded = true;    if (!window.dev || !window.dev.i18n) {        wk.importArticle({ type: "script", article: "u:dev:MediaWiki:I18n-js/code.js" });   }    // Constant for future testing    const DEBUG = false;    //I18n-js    var $i18n;    /**     * @class MassEdit     * @classdesc The central MassEdit class     */    var MassEdit = {        meta: {            author: "User:Eizen",            created: "05/02/17",            lastEdit: "03/09/18",            version: "2.4.4"        },        hasRights: new RegExp(["(user)"].join("")).test(wk.wgUserGroups.join(" ")),        legalChars: new RegExp("^[" + wk.wgLegalTitleChars + "]*$"),        /**         * @method addLogEntry         * @description Method allows for quick adding of a MassEdit log entry         *              to the appropriate text field.         * @param {String} $key - The name of the JSON field         * @returns {void}         */        addLogEntry: function ($key) {            jQuery("#massEdit-log").prepend($i18n.msg($key).escape + " ");        },        /** * @method addLogEntry * @description "Overloaded" two-parameter variation of the method above *             that accepts a JSON key and an entry substitute for $1 *             or $2. * @param {String} $key - The name of the JSON field * @param {String} $entry - Name of the page to substitute * @returns {void} */       addLogEntry: function ($key, $entry) { jQuery("#massEdit-log").prepend(               $i18n.msg($key, $entry).escape + " "); },       /**         * @method constructItem * @description Method returns a completed *             representing the menu link item. Is comprised of a        *              link inside a list item. * @param {String} $text - Text to be displayed in the item and title * @returns {String} */       constructItem: function ($text) { return mw.html.element("li", {               "class": "overflow",                "id": "massEdit-li"            }, new mw.html.Raw( mw.html.element("a", {                   "id": "massEdit-a",                    "href": "#",                    "title": $text                }, $text) ));       },        /**         * @method isLegalPage * @description Utility function used to test if inputted page name *             matches the legal characters regex. Returns a boolean *             flag depending on result. * @param {String} $page - Inputted page name * @returns {boolean} */       isLegalPage: function ($page) { if (!this.legalChars.test($page)) { jQuery("#massEdit-modal-form")[0].reset; this.addLogEntry("modalSecurity"); return false; } else { return true; }       },        /**         * @method displayModal * @description Method constructs and displays the main user interface. *             Injects custom CSS prior to construction and handles all *             button click events. * @param {String} $modalHTML - The modal HTML layout * @returns {void} */       displayModal: function ($modalHTML) { var that = this; mw.util.addCSS(               ".massEdit-menu," +                ".massEdit-textbox {" +                    "width: 100%;" +                    "padding: 0;" +                "}" +                ".massEdit-textarea {" +                    "height: 50px;" +                    "width: 100%;" +                    "padding: 0;" +                    "overflow: auto;" +                "}" +                "#massEdit-log {" +                    "height: 55px;" +                    "width: 100%;" +                    "border: 1px solid;" +                    "font-family: monospace;" +                    "background: #fff;" +                    "color: #aeaeae;" +                    "overflow: auto;" +                    "padding:0;" +                "}"            ); ui.init(["modal"]).then(function (modal) {               var config = {                    vars: {                        id: "massEdit-modal",                        size: "medium",                        title: $i18n.msg("itemTitle").escape,                        content: $modalHTML,                        buttons: [{                            vars: {                                value: $i18n.msg("buttonCancel").escape,                                classes: ["normal", "primary"],                                data: [{                                    key: "event",                                    value: "cancel"                                }]                            }                        }, {                            vars: {                                value: $i18n.msg("buttonClear").escape,                                classes: ["normal", "primary"], data: [{ key: "event", value: "clear" }]                           }                        }, {                            vars: { value: $i18n.msg("buttonSubmit").escape, classes: ["normal", "primary"], data: [{ key: "event", value: "submit" }]                           }                        }]                    }                };                modal.createComponent(config, function (massEditModal) {                    massEditModal.bind("cancel", function  { massEditModal.trigger("close"); });                   massEditModal.bind("clear", function  { jQuery("#massEdit-modal-form")[0].reset; });                    massEditModal.bind("submit", function  { that.main; });                   massEditModal.show;                }); });           // Disable replacements menu depending on current selected option            jQuery(document).on("change", "#massEdit-actionType", function  { if (jQuery("#massEdit-actionType").val === "replace") { jQuery("#massEdit-replaceThis-value") .prop("disabled", false); } else { jQuery("#massEdit-replaceThis-value") .prop("disabled", true); }           });        },        /**         * @method getContent         * @description This method retrieves the content of the inputted page,         *              including information about its time of creation and         *              relevant timestamp info. Used exclusively by the find         *              and dropdown option.         * @param {String} $action - Editing action (prepend, append, replace)         * @param {String} $editSummary - Edit summary         * @param {String} $page - The page in question         * @param {String} $newContent - New text to replace the target         * @param {String} $replace - The target to be replaced in the callback         * @param {function} callback - The callback handler         */        getContent: function ($action, $editSummary, $page, $newContent, $replace, callback) {           var that = this;            this.api.get({ action: "query", prop: "info|revisions", intoken: "edit", titles: $page, rvprop: "content|timestamp", rvlimit: "1", indexpageids: "true", format : "json" }).done(function ($data) { if (!$data.error) { callback(          // handleContent                        that,           // this                        $action,        // "replace"                        $editSummary,   // "#massEdit-summary-value"                        $data,          // $data                        $page,          // $pagesArray[$counter]                        $newContent,    // "#massEdit-content-value"                        $replace        // "#massEdit-replaceThis-value"                    ); }           });        },        /**         * @method handleContent         * @description Callback function for  . Sifts         *              through included data and passes relevant bits to the         *                method. Used exclusively by the         *              find and replace dropdown option.         * @param {this} that - Scope variable         * @param {String} $action - Editing action (prepend, append, replace)         * @param {String} $editSummary - Edit summary         * @param {JSON} $data - Passed data from           * @param {String} $page - Specific page in question         * @param {String} $newContent - New text to replace the target         * @param {String} $replaceThis - Text to be replaced by $newContent         * @returns {void}         */        handleContent: function (that, $action, $editSummary, $data, $page, $newContent, $replaceThis) {           // Check if page actually exists            if (Object.keys($data.query.pages)[0] === "-1") {                jQuery("#massEdit-modal-form")[0].reset;                that.addLogEntry("noSuchPage", $page);                return;            }            var $newText;            var $result = $data.query.pages[Object.keys($data.query.pages)[0]];            var $text = $result.revisions[0]["*"];            var $timestamp = $result.revisions[0].timestamp;            var $starttimestamp = $result.starttimestamp;            var $token = $result.edittoken;            // Replace all instances of chosen text with inputted new text            $newText = $text.split($replaceThis).join($newContent);            // Check if old & new revisions are identical in content            if ($newText === $text) {                jQuery("#massEdit-log").prepend( $i18n.msg("noMatch", $replaceThis, $page).escape + " "               );            } else {                that.editPage(that, $page, $newText, $action, $editSummary, $timestamp, $starttimestamp, $token);           }        },        /**         * @method editPage         * @description The one-size-fits-all editing handler for use by all         *              three main MassEdit functions. Takes several different         *              numbers of input parameters depending on the action to         *              be taken by the handler.         * @param {this} that - Scope variable         * @param {String} $page - The page to be edited         * @param {String} $content - The content to be added to the page         * @param {String} $action - Editing action (prepend, append, replace)         * @param {String} $editSummary - Edit summary         * @param {String} $timestamp - Optional, for replace option only         * @param {String} $starttimestamp - Optional, for replace option only         * @param {String} $token - Optional, for replace option only * @returns {void} */       editPage: function (that, $page, $content, $action, $editSummary,                $timestamp, $starttimestamp, $token) { // Edit without editing; for testing purposes if (DEBUG) { that.addLogEntry("editSuccess", $page); return; }           // Default base properties var $params = { action: "edit", minor: true, bot: true, title: $page, summary: $editSummary };           // Set additional Object properties depending on action to be taken switch ($action) { case "prepend": $params.prependtext = $content; $params.token = mw.user.tokens.get("editToken"); break; case "append": $params.appendtext = $content; $params.token = mw.user.tokens.get("editToken"); break; case "replace": $params.text = $content; $params.basetimestamp = $timestamp; $params.startimestamp = $starttimestamp; $params.token = $token; break; }           that.api.post($params).done(function ($data) {                jQuery("#massEdit-modal-form")[0].reset;                if (!$data.error) {                    that.addLogEntry("editSuccess", $page);                } else {                    that.addLogEntry("editFailure", $page);                }            }); },       /**         * @method getNamespaceMembers * @description As the name implies, this method returns the results of        *              a request for an inputted namespace's associated page *             contents. * @param {String} $namespace - Number of the namespace in question * @return {JSON} */       getNamespaceMembers: function ($namespace) { return jQuery.ajax({               type: "GET",                url: mw.util.wikiScript("api"),                data: {                    action: "query",                    list: "allpages",                    aplimit: "max",                    apnamespace: $namespace,                    format: "json"                }            }); },       /**         * @method getCategoryMembers * @description As the name implies, this method returns the results of        *              a request for an inputted category's associated page *             contents. * @param {String} $category - Name of the category in question * @return {JSON} */       getCategoryMembers: function ($category) { return jQuery.ajax({               type: "GET",                url: mw.util.wikiScript("api"),                data: {                    action: "query",                    list: "categorymembers",                    cmtitle: $category,                    cmprop: "title",                    cmdir: "desc",                    cmlimit: "max",                    format: "json"                }            }); },       /**         * @method membersHandler * @description This method, inspired by Java-style reflection, is a        *              general purpose handler for use by both namespace and *             category bulk editing. The method accepts either the *             <tt>getCategoryMembers</tt> or         *              <tt>getNamespaceMembers<tt> methods as the requests of         *              choice, running basically the same process with the *             results of each once all calls have been completed. *

*

*             Basically, once the calls have been made, the method *             assembles all the pages from the request results and *             pushes them into an array for processing by the *             <tt>actionHandler</tt> method. * @param {String[]} $inputArray * @param {String} $newContent * @param {String} $toReplace * @param {int} $actionIndex * @param {String} $action * @param {String} $editSummary * @param {function} getMembers * @param {String} $queryProperty * @returns {void} */       membersHandler: function ($inputArray, $newContent, $toReplace,                $actionIndex, $action, $editSummary, getMembers,                $queryProperty) { var that = this; var $members; var $requests; var $arguments; var $defer; var $data; $members = []; $requests = []; $arguments = []; $inputArray.forEach(function ($member) {               if ( $queryProperty === "categorymembers" && !$member.startsWith("Category:") ) {                   $member = "Category:" + $member;                }                if ( ( // If is category-based and member is legal                       $queryProperty === "categorymembers" &&                        that.isLegalPage($member)                    ) || ( // If is namespace-based and member is integer                       $queryProperty === "allpages" &&                        $member.match(/^[0-9]+$/) !== null                    ) ) {                   $members.push($member);                    $requests.push(getMembers($member));                }            }); if (               !$members.length ||                !$requests.length ||                $members.length !== $requests.length            ) { return; }           $inputArray = []; $defer = jQuery.when.apply(jQuery, $requests); $defer.done(function {                if ($requests.length === 1) {                    $arguments.push(arguments);                } else {                    $arguments = Array.prototype.slice.call(arguments);                }                jQuery.each($arguments, function ($index, $results) { if ($results[1] === "success") { $data = $results[0].query[$queryProperty]; if ($data === undefined || $data.length === 0) { that.addLogEntry("noSuchPage", $members[$index]); return; }                       $data.forEach(function ($page) {                            $inputArray.push($page.title);                        }); }               });                if ($inputArray.length) {                    that.actionHandler($inputArray, $newContent, $toReplace, $actionIndex, $action, $editSummary);               }            }); },       /**         * @method actionHandler * @description This function invokes methods based on user's desired *             action. If the user is not in the proper user rights *             group, access is denied. If no action is selected, the *             user is prompted to select an action. *             <tt>setInterval</tt> is employed to ensure that the *             script does not make too many consecutive content GETs *             or edit POSTs; replaces <tt>forEach</tt> *             implementation. *

*

*             Addition of global pages-based find-and-replace option *             replaces old find-and-delete option, and now checks for *             cases of empty pages or empty target text. * @param {String[]} $inputArray * @param {String} $newContent * @param {String} $toReplace * @param {int} $actionIndex * @param {String} $action * @param {String} $editSummary * @returns {void} */       actionHandler: function ($inputArray, $newContent, $toReplace,                $actionIndex, $action, $editSummary) { var that = this; var $counter = 0; var $editInterval; switch ($actionIndex) { case 0: // No action selected this.addLogEntry("noOptionSelected"); break; case 1: case 2: // Edit methods (prepend and append) this.addLogEntry("loading"); $editInterval = setInterval(function {                    if (that.isLegalPage($inputArray[$counter])) {                        that.editPage(that, $inputArray[$counter], $newContent, $action, $editSummary);                   }                    $counter++;                    if ($counter === $inputArray.length) {                        clearInterval($editInterval);                    }                }, that.config.editInterval); break; case 3: // Find and replace this.addLogEntry("loading"); $editInterval = setInterval(function {                    if (that.isLegalPage($inputArray[$counter])) {                        that.getContent($action, $editSummary, $inputArray[$counter], $newContent, $toReplace, that.handleContent);                   }                    $counter++;                    if ($counter === $inputArray.length) {                        clearInterval($editInterval);                    }                }, that.config.editInterval); break; }       },        /**         * @method main * @description The main method handles the collection of user input *             from the GUI modal and tests against a series of base *             cases to ensure ill-formed or illegitimate input is not *             included in the program's operations. Furthermore, the *             new category-based function necessitated the removal of         *              some old code used to execute different actions (i.e.         *              prepend, append, etc.) to a different method, namely *             <tt>actionHandler</tt>. The main method now handles the *             acquisition of category members from user input cats, *             passing the array of pages to the handler above. *

*

*             Addition of global pages-based find-and-replace option *             replaces old find-and-delete option, and now checks for *             cases of empty pages or empty target text. * @returns {void} */       main: function  { var that = this; // Values of textareas var $newContent = jQuery("#massEdit-content-value")[0].value; var $toReplace = jQuery("#massEdit-replaceThis-value")[0].value; var $pagesInput = jQuery("#massEdit-pages-value")[0].value; var $editSummary = jQuery("#massEdit-summary-value")[0].value; var $pagesArray = $pagesInput.split(/[\n]+/); // Dropdown menu var $actionIndex = jQuery("#massEdit-actionType")[0].selectedIndex; var $action = jQuery("#massEdit-actionType").val; var $typeIndex = jQuery("#massEdit-contentType")[0].selectedIndex; // Is not in the proper rights group if (!this.hasRights) { jQuery("#massEdit-modal-form")[0].reset; this.addLogEntry("modalUserRights"); return; // No pages included } else if (!$pagesInput) { this.addLogEntry("noPages"); return; // Is either append/prepend with no content input included } else if ($action !== "replace" && !$newContent) { this.addLogEntry("noContent"); return; // Is find-and-replace with no target content included } else if ($action === "replace" && !$toReplace) { this.addLogEntry("noTarget"); return; // If user forgot to select dropdown options (no reset b/c annoying) } else if ($actionIndex === 0 || $typeIndex === 0) { this.addLogEntry("noOptionSelected"); return; // If edit summary is greater than permitted max of 800 characters } else if ($editSummary.length > 800) { this.addLogEntry("overlongSummary"); return; }           switch ($typeIndex) { case 1: // Loose pages that.actionHandler($pagesArray, $newContent, $toReplace,                   $actionIndex, $action, $editSummary); break; case 2: // Categories that.membersHandler($pagesArray, $newContent, $toReplace,                   $actionIndex, $action, $editSummary,                    that.getCategoryMembers, "categorymembers"); break; case 3: // Namespaces that.membersHandler($pagesArray, $newContent, $toReplace,                   $actionIndex, $action, $editSummary,                    that.getNamespaceMembers, "allpages"); break; }       },        /**         * @method init * @description Method initializes the program, assembling the toolbar *             link and handling click events. Config options are set *             per user input or the defaults. * @param {JSON} $lang - I18n-js content * @returns {void} */       init: function ($lang) { var that = this; $i18n = $lang; $i18n.useContentLang; this.api = new mw.Api; this.config = jQuery.extend({               editInterval: 1500            }, window.massEditConfig); $i18n.useUserLang; /**            * Handle removal of   right for bots/users * Current rate limit for default user/sysop/etc. is 40 edits/minute * Current rate limit for bot (not bot-global) is 80 edits/minute * @see SUS-4775</a> * @see VariablesBase.php</a> */           if (                jQuery.inArray("bot", wk.wgUserGroups) !== -1 &&                this.config.editInterval < 750            ) { this.config.editInterval = 750; // Reset to max 80 edits/minute } else if (               jQuery.inArray("user", wk.wgUserGroups) !== -1 &&                this.config.editInterval < 1500            ) { this.config.editInterval = 1500; // Reset to max 40 edits/minute }           var $modalHTML = "<form id='massEdit-modal-form' class='WikiaForm '>" + " " +                   " " + $i18n.msg("modalSelect").escape + " " +                       "<select size='1' id='massEdit-actionType'" + "class='massEdit-menu' name='action'>" + "<option selected=''>" + $i18n.msg("modalSelect").escape + " " +                           "<option value='prepend'>" + $i18n.msg("dropdownPrepend").escape + " " +                           "<option value='append'>" + $i18n.msg("dropdownAppend").escape + " " +                           "<option value='replace'>" + $i18n.msg("dropdownReplace").escape + " " +                       " " +                        " " +                    " " +                    " " +                    " " + $i18n.msg("modalContentType").escape + " " +                       "<select size='1' id='massEdit-contentType'" + "class='massEdit-menu' name='action'>" + "<option selected=''>" + $i18n.msg("modalContentType").escape + " " +                           "<option value='pages'>" + $i18n.msg("dropdownPages").escape + " " +                           "<option value='categories'>" + $i18n.msg("dropdownCategories").escape + " " +                           "<option value='namespaces'>" + $i18n.msg("dropdownNamespaces").escape + " " +                       " " +                        " " +                    " " +                    " " +                    " " + $i18n.msg("modalContentTitle").escape + " " +                       "<textarea id='massEdit-content-value' " + "class='massEdit-textarea' placeholder='" + $i18n.msg("modalContentPlaceholder").escape + "'/>" +                       " " +                    " " +                    " " +                    " " + $i18n.msg("modalReplaceTitle").escape + " " +                       "<textarea id='massEdit-replaceThis-value' " + "class='massEdit-textarea' placeholder='" + $i18n.msg("modalReplacePlaceholder").escape + "' disabled/>" + " " +                   " " +                    " " +                    " " + $i18n.msg("modalPagesTitle").escape + " " +                       "<textarea id='massEdit-pages-value' " + "class='massEdit-textarea' placeholder='" + $i18n.msg("modalPagesPlaceholder").escape + "'/>" +                       " " +                    " " +                    " " +                    " " + $i18n.msg("modalSummaryTitle").escape + " " +                       "<input type='textbox' id='massEdit-summary-value'" + "class='massEdit-textbox' />" + " " +                   " " +                " " +                " " +                " " +            " " +            " " + $i18n.msg("modalLog").escape + " " + " " +           " ";            var $tbElement = this.constructItem($i18n.msg("itemTitle").plain); jQuery($tbElement).prependTo("#my-tools-menu").click(function {                that.displayModal($modalHTML);            }); }   };    mw.hook("dev.i18n").add(function ($i18n) {        jQuery.when( $i18n.loadMessages("MassEdit"), mw.loader.using(["mediawiki.util", "mediawiki.api"]) ).done(jQuery.proxy(MassEdit.init, MassEdit));   }); });

/* * Mass Categorization * @description (De)Categorize listed multiple pages. * @author Ozuzanna, Dorumin * @todo Add more i18n * Added option for (Dessamator) * Updated: (Dorumin) *    - Some optimization and code-cleaning. *    - Re-added the replace function *    - Now can add, remove, and replace multiple categories at once (but not all three modes at the same time). *    - Now prompts if you try to exit the modal while running. *    - The broad option now doesn't replace stuff like "Test 123", but I kept the option in anyways. */ mw.loader.using('mediawiki.api').then(function {   var groups = window.MassCategorizationGroups || ['user'];    window.MassCategorizationLoaded = true;    importArticle({ type: 'style', article: 'u:dev:MediaWiki:MassCategorization.css' });	var i18n = {		//language list - start		en: {			title: "Mass Categorization",			mode: "Mode",			add: "Add",			remove: "Remove",			replace: "Replace",			category: "Category",			categoryPlural: "Categories",			replaceWith: "Replace with",			matching: "Matching",			generalMatching: "General (does not account for piped categories)",			broadMatching: "Broad (takes care of piped links)",			noInclude: "Do not include in transclusion (for templates)",			caseSensitive: "Case sensitive (removal and replace only)",			instructions: "Put the name of each page you want to categorize on a separate line",			outputInitial: "Any errors encountered will appear below",			cancel: "Cancel",			addCategoryContents: "Add category contents",			initiate: "Initiate",			categoryPrompt: "Please enter the category name (no category prefix)",			doesNotExist: "$1 does not exist",			failedToGetContents: "Failed to get contents of $1", categoryAlert: "Please enter at least one category", warning: "Warning", closeModalWarning: "Are you sure you want to close the modal without finishing?", close: "Close", finished: "Finished", nothingLeftToDo: "Nothing left to do, or next line is blank", noCategoryToReplace: "No $1 to replace with entered", pageNotExist: "Page $1 does not exist", addSummary: "Adding $1 (automatic)", addFail: "Failed to add $1 to $2", categoryAlready: "$1 already has the category $2 or an error was encountered; it has been skipped", categoryCheckFail: "Category check failed for $1; it has been skipped", removeNotFound: "$1 was not found on $2", removeFail: "Failed to remove $1 from $2", removeSuccess: "$1 successfully removed from $2", removeSummary: "Removing $1 (automatic)", replaceFail: "Failed to replace $1 on $2", replaceSuccess: "Category successfully replaced on $1", replaceSummary: "Replacing $1 with $2 (automatic)", multiReplaceSummary: "Replacing categories: $1 (automatic)", noCategoryReplace: "No category to replace", automatic: "automatic" },		be: { title: "Масавая катэгарызацыя", mode: "Дзеянне", add: "Дадаць", remove: "Выдаліць", replace: "Перасунуць", category: "Катэгорыя", categoryPlural: "Катэгорыі", replaceWith: "Замяніць на", matching: "Параўнанне", generalMatching: "Звычайнае (не ўлічвае асобныя катэгорыі)", broadMatching: "Пашыранае (улічвае асобныя спасылкі)", noInclude: "Не ўлічваць улучэння (для шаблонаў)", caseSensitive: "З улікам рэгістра (толькі для опцый выдаленні і перасоўванні)", instructions: "Змясцуйце тут назву старонкі, якую вы хочаце змясціць у катэгорыю ў асобным радку", outputInitial: "Тут будуць з\'яўляцца ўсе абмылы", cancel: "Скасаванне", addCategoryContents: "Дадаць змесціва катэгорыі", initiate: "Запусціць", categoryPrompt: "Калі ласка, пакажыце назву катэгорыі (без прэфікса Катэгорыя:)", doesNotExist: "$1 не існуе", failedToGetContents: "Не атрымалася стварыць $1", categoryAlert: "Калі ласка, пастаўце хоць бы адну катэгорыю", warning: "Папярэджанне", closeModalWarning: "Вы ўпэўнены, што хочаце адключыць гэты скрыпт без захавання якіх-небудзь катэгорый?", close: "Зачыніць", finished: "Завершана", nothingLeftToDo: "Вам не трэба нічога рабіць далей ці наступны радок пусты", noCategoryToReplace: "Вы не можаце перасунуць старонкі $1", pageNotExist: "Старонка $1 не існуе", addSummary: "Дададзена $1 (аўтаматычна)", addFail: "Не атрымалася дадаць $1 у $2", categoryAlready: "$1 вужы ў катэгорыі $2 ці адбылася абмыла, дадзеная назва была прапушчана", categoryCheckFail: "Катэгорыя $1 не знойдзена; дадзеная назва была прапушчана", removeNotFound: "$1 не было знойдзена ў $2", removeFail: "Не атрымалася выдаліць $1 з $2", removeSuccess: "$1 было выдалена з $2", removeSummary: "Выдалена з $1 (аўтаматычна)", replaceFail: "Не атрымалася замяніць $1 на $2", replaceSuccess: "Катэгорыя паспяхова заменена на $1", replaceSummary: "Замена $1 на $2 (аўтаматычна)", multiReplaceSummary: "Замена катэгорый: $1 (аўтаматычна)", noCategoryReplace: "Няма катэгорыі для замены", automatic: "аўтаматычна" },		ca: { title: 'Categorització en massa', mode: 'Manera', add: 'Afegeix', remove: 'Treu', replace: 'Reemplaça', category: 'Categoria', categoryPlural: 'Categories', replaceWith: 'Reemplaça amb', matching: 'Coincidències', generalMatching: "General (no té en compte les categories amb barra)", broadMatching: "Extensa (té en compte les categories amb barra)", noInclude: "No ho incloguis a la transclusió (per a plantilles)", caseSensitive: "Té en compte majúscules i minúscules (només en les maneres de treure i reemplaçar)", instructions: "Introdueix el nom de cada pàgina que vulguis categoritzar en una línia separada", outputInitial: "Qualsevol error trobat apareixerà a baix", cancell: "Canceŀla", addCategoryContents: "Afegeix contingut de categoria", initiate: "Inicia", categoryPrompt: "Si us plau, introdueix el nom de la categoria (sense el prefix de Categoria)", doesNotExist: "$1 no existeix", failedToGetContents: "Error per carregar continguts de $1", categoryAlert: "Introdueix almenys una categoria", warning: "Advertència", closeModalWarning: "Estàs segur que vols tancar el mòdul sense acabar?", close: "Tanca", finished: "Finalitzat", nothingLeftToDo: "Res més per fer, o la següent línia està en blanc", noCategoryToReplace: "Cap $1 per reemplaçar s\'ha introduït", pageNotExist: "La pàgina $1 no existeix", addSummary: "Afegint $1 (automàtic)", addFail: "Error en afegir $1 a $2", categoryAlready: "$1 ja conté la categoria $2 o algun error s\'ha trobat; ha estat omesa", categoryCheckFail: "La verificació de categories ha fallat per a la pàgina $1; aquesta ha estat omesa", removeNotFound: "$1 no s\'ha trobat a la pàgina $2", removeSummary: "Traient $1 (automàtic)", removeFail: "Error traient $1 de la pàgina $2", replaceSummary: "Reemplaçant $1 amb $2 (automàtic)", multiReplaceSummary: 'Reemplaçant categories: $1 (automàtic)', removeSuccess: "$1 s\'ha tret de la pàgina $2 amb èxit", replaceFail: "Error en reemplaçar $1 a la pàgina $2", replaceSuccess: "Categoria reemplaçada amb èxit a la pàgina $1", noCategoryReplace: "Cap categoria per reemplaçar", automatic: "automàtic" },		de: { title: "Mehrfaches Kategorisieren", mode: "Modus", add: "Hinzufügen", remove: "Entfernen", replace: "Ersetzen", category: "Kategorie", categoryPlural: "Kategorien", replaceWith: "Ersetze mit", matching: "Übereinstimmungen", generalMatching: "Allgemein (ausgenommen Kategorie-Links mit senkrechtem Strich)", broadMatching: "Breit (berücksichtigt Links mit senkrechtem Strich)", noInclude: "Schließe Einbindungen nicht mit ein (für Vorlagen)", caseSensitive: "Groß-/Kleinschreibung beachten (nur Entfernen und Ersetzen)", instructions: "Schreibe den Namen jeder Seite, die du kategorisieren willst, jeweils in eine eigene Zeile", outputInitial: "Alle aufgetretenden Fehler werden unten angezeigt", cancel: "Abbrechen", addCategoryContents: "Kategorien-Inhalte hinzufügen", initiate: "Start", categoryPrompt: "Bitte füge den Namen der Kategorie ein (kein Kategorie-Präfix)", doesNotExist: "$1 existiert nicht", failedToGetContents: "Abrufen der Inhalte aus $1 fehlgeschlagen", categoryAlert: "Bitte mindestens eine Kategorie eingeben", warning: "Warnung", closeModalWarning: "Willst du das Modul wirklich schließen ohne deine Arbeit zu beenden?", close: "Schließen", finished: "Erledigt", nothingLeftToDo: "Nichts mehr zu tun, oder die nächste Zeile ist leer", noCategoryToReplace: "Keine $1 mit der eingegebenen Kategorie zu ersetzen", pageNotExist: "Die Seite $1 existiert nicht", addSummary: "Füge $1 hinzu (automatisch)", addFail: "Das Hinzufügen von $1 zu $2 ist fehlgeschlagen", categoryAlready: "$1 hat die Kategorie $2 bereits oder ein Fehler ist aufgetreten; die Seite wurde übersprungen", categoryCheckFail: "Überprüfung der Kategorie für $1 fehlgeschlagen; sie wurde übersprungen", removeNotFound: "$1 wurde auf $2 nicht gefunden", removeFail: "Das Entfernen von $1 von $2 ist fehlgeschlagen", removeSuccess: "$1 erfolgreich von $2 entfernt", removeSummary: "Entferne $1 (automatisch)", replaceFail: "Das Ersetzen von $1 auf $2 ist fehlgeschlagen", replaceSuccess: "Kategorie erfolgreich auf $1 ersetzt", replaceSummary: "Ersetze $1 mit $2 (automatisch)", multiReplaceSummary: "Ersetze Kategorien: $1 (automatisch)", noCategoryReplace: "Keine Kategorie zum Ersetzen", automatic: "automatisch" },		es: { title: 'Categorización en masa', mode: 'Modo', add: 'Añadir', remove: 'Quitar', replace: 'Reemplazar', category: 'Categoría', categoryPlural: 'Categorías', replaceWith: 'Reemplazar con', matching: 'Coincidencias', generalMatching: "General (no toma en cuenta las categorías con barra)", broadMatching: "Extensa (toma en cuenta las categorías con barra)", noInclude: "No incluir en transclusión (para plantillas)", caseSensitive: "Toma en cuenta mayúsculas y minúsculas (solo en las modos de quitar y reemplazar)", instructions: "Introduce el nombre de cada página que quieras categorizar en una línea separada", outputInitial: "Cualquier error encontrado aparecerá abajo", cancel: "Cancelar", addCategoryContents: "Añadir contenido de categoría", initiate: "Iniciar", categoryPrompt: "Por favor, introduce el nombre de la categoría (sin el prefijo de Categoría)", doesNotExist: "$1 no existe", failedToGetContents: "Error para cargar contenidos de $1", categoryAlert: "Introduce al menos una categoría", warning: "Advertencia", closeModalWarning: "¿Estás seguro de que quieres cerrar el módulo sin terminar?", close: "Cerrar", finished: "Finalizado", nothingLeftToDo: "Nada más que hacer, o la siguiente línea está en blanco", noCategoryToReplace: "Ninguna $1 para reemplazar se ha introducido", pageNotExist: "La página $1 no existe", addSummary: "Añadiendo $1 (automático)", addFail: "Error al añadir $1 a $2", categoryAlready: "$1 ya contiene la categoría $2 o algún error se ha encontrado; ha sido omitida", categoryCheckFail: "La verificación de categorías ha fallado para la página $1; ésta ha sido omitida", removeNotFound: "$1 no se ha encontrado en la página $2", removeSummary: "Removiendo $1 (automático)", removeFail: "Error removiendo $1 de la página $2", replaceSummary: "Reemplazando $1 con $2 (automático)", multiReplaceSummary: 'Reemplazando categorías: $1 (automático)', removeSuccess: "$1 se ha removido de la página $2 con éxito", replaceFail: "Error al reemplazar $1 en la página $2", replaceSuccess: "Categoría reemplazada con éxito en la página $1", noCategoryReplace: "Ninguna categoría para reemplazar", automatic: "automático" },		fr: { title: 'Catégorisation massive', mode: 'Façon', add: 'Ajouter', remove: 'Enlever', replace: 'Remplacer', category: 'Catégorie', categoryPlural: 'Catégories', replaceWith: 'Remplacer avec', matching: 'Coïncidences', generalMatching: "Général (ne prend pas en compte les catégories avec barre)", broadMatching: "Étendue (en prenant en compte les catégories avec barre)", noInclude: "Ne pas inclure dans la transclusion (pour les modèles)", caseSensitive: "En prenant en compte majuscules et minuscules (seulement dans les façons d\'enlever et remplacer)", instructions: "Introduisez le nom de chaque page dans n\'importe quelle page que vous voulez catégoriser dans une ligne séparée", outputInitial: "N\'importe quelle erreur trouvée apparaîtra en bas", cancel: "Annuler", addCategoryContents: "Ajouter le contenu de la catégorie", initiate: "Entamer", categoryPrompt: "S\'il vous plaît, introduisez le nom de la catégorie (sans le préfixe de Catégorie)", doesNotExist: "$1 n\'existe pas", failedToGetContents: "Erreur lors du chargement des contenus de $1", categoryAlert: "Introduisez au moins une catégorie", warning: "Avertissement", closeModalWarning: "Êtes-vous sûr que vous voulez fermer le module sans terminer ?", close: "Fermer", finished: "Terminé", nothingLeftToDo: "Il n'y a plus rien à faire, ou la suivante ligne est vide", noCategoryToReplace: "Aucune $1 pour remplacer s\'est introduit", pageNotExist: "La page $1 n\'existe pas", addSummary: "En train d\'ajouter $1 (automatique)", addFail: "Erreur lors de l\'ajout de la page $1 à $2", categoryAlready: "$1 déjà contient la catégorie $2 ou quelque erreur s\'est trouvée; il a été omis", categoryCheckFail: "La vérification de catégories a failli pour la page $1; elle a été omise", removeNotFound: "$1 ne s\'est pas trouvé sur la page $2", removeSummary: "En train de supprimer $1 (automatique)", removeFail: "Erreur lors de la suppression de $1 de la page $2", replaceSummary: "En train de remplacer $1 avec $2 (automatique)", multiReplaceSummary: 'En train de remplacer les catégories: $1 (automatique)', removeSuccess: "$1 s\'est supprimé de la page $2 avec succès", replaceFail: "Erreur lors du remplacement de $1 sur la page $2", replaceSuccess: "Catégorie remplacée avec succès sur la page $1", noCategoryReplace: "Aucune catégorie pour remplacer", automatic: "automatique" },		gl: { title: 'Categorización en masa', mode: 'Modo', add: 'Engadir', remove: 'Quitar', replace: 'Substituír', category: 'Categoría', categoryPlural: 'Categorías', replaceWith: 'Substituír con', matching: 'Coincidencias', generalMatching: "Xeral (non toma en conta as categorías con barra)", broadMatching: "Extensa (toma en conta as categorías con barra)", noInclude: "Non incluír en transclusión (para modelos)", caseSensitive: "Toma en conta maiúsculas e minúsculas (só nos modos de quitar e substituír)", instructions: "Introduce o nome de cada páxina que quixeres categorizar nunha liña separada", outputInitial: "Calquera erro atopado aparecerá abaixo", cancel: "Cancelar", addCategoryContents: "Engadir contido de categoría", initiate: "Iniciar", categoryPrompt: "Por favor, introduce o nome da categoría (sen o prefixo de Categoría)", doesNotExist: "$1 non existe", failedToGetContents: "Erro ao cargar contidos de $1", categoryAlert: "Introduce polo menos unha categoría", warning: "Advertencia", closeModalWarning: "Estás seguro de que queres pechar o módulo sen terminar?", close: "Pechar", finished: "Finalizado", nothingLeftToDo: "Máis nada para facer, ou a seguinte liña está en branco", noCategoryToReplace: "Ningunha $1 para substituír foi introducida", pageNotExist: "A páxina $1 non existe", addSummary: "A engadir $1 (automático)", addFail: "Erro ao engadir $1 a $2", categoryAlready: "$1 xa contén a categoría $2 ou algún erro foi atopado; daquela foi omitida", categoryCheckFail: "A verificación de categorías fallou para a páxina $1; daquela foi omitida", removeNotFound: "$1 non se atopou na páxina $2", removeSummary: "A remover $1 (automático)", removeFail: "Erro ao remover $1 da páxina $2", replaceSummary: "A substituír $1 con $2 (automático)", multiReplaceSummary: 'A substituír categorías: $1 (automático)', removeSuccess: "$1 removeuse da páxina $2 con éxito", replaceFail: "Erro ao substituír $1 na páxina $2", replaceSuccess: "Categoría substituída con éxito na páxina $1", noCategoryReplace: "Ningunha categoría para substituír", automatic: "automático" },		hi: { title: "मास वर्गीकरण", mode: "मोड", add: "जोड़ें", remove: "निकालें", replace: "बदलें", category: "श्रेणी", categoryPlural: "चैनल", replaceWith: "के साथ बदलें", matching: "मिलान", generalMatching: "जनरल (पहुंचाया श्रेणियों के लिए खाते में नहीं है)", broadMatching: "ब्रॉड (पहुंचाया लिंक का ख्याल रखता है)", noInclude: "(टेम्पलेट्स के लिए) ट्रांसक्लुजन में शामिल न करें", caseSensitive: "प्रकरण संवेदनशील (हटाने और केवल जगह)", instructions: "प्रत्येक पृष्ठ आप एक अलग लाइन पर वर्गीकृत करने के लिए चाहते हैं के नाम रखो", outputInitial: "नीचे दिखाई देगा का सामना करना पड़ा किसी भी त्रुटि", cancel: "रद्द", addCategoryContents: "जोड़ें श्रेणी सामग्री", initiate: "आरंभ", categoryPrompt: "श्रेणी नाम (कोई श्रेणी उपसर्ग) दर्ज करें", doesNotExist: "$1 मौजूद नहीं है", failedToGetContents: "$1 की सामग्री को पाने में विफल", categoryAlert: "कम से कम एक श्रेणी दर्ज करें", warning: "चेतावनी", closeModalWarning: "क्या आप परिष्करण के बिना मोडल बंद करना चाहते हैं?", close: "बंद", finished: "समाप्त", nothingLeftToDo: "कुछ भी नहीं करना छोड़ दिया है, या अगली पंक्ति को खाली है", noCategoryToReplace: "नहीं $1 में प्रवेश के साथ बदलने के लिए", pageNotExist: "पन्ना $1 मौजूद नहीं है", addSummary: "जोड़ना $1 (स्वचालित)", addFail: "$1 $2 जोड़ने में विफल", categoryAlready: "$1 पहले से ही श्रेणी $2 है या एक त्रुटि का सामना करना पड़ा था, यह छोड़ दिया गया है", categoryCheckFail: "श्रेणी की जांच $1 के लिए विफल रहा है, इसे छोड़ दिया गया है", removeNotFound: "$1 $2 पर नहीं मिला था", removeFail: "$2 से $1 को दूर करने में विफल", removeSuccess: "$1 $2 से सफलतापूर्वक हटा दिया", removeSummary: "हटाने $1 (स्वचालित)", replaceFail: "$2 $1 करने में असफ़ल", replaceSuccess: "श्रेणी सफलतापूर्वक $1 पर प्रतिस्थापित", replaceSummary: "$2 (स्वचालित) के साथ $1 की जगह", multiReplaceSummary: "श्रेणियों की जगह: $1 (स्वचालित)", noCategoryReplace: "नहीं श्रेणी को बदलने के लिए", automatic: "स्वचालित" },		it: { title: 'Categorizzazione massiccia', mode: 'Modo', add: 'Aggiungi', remove: 'Togli', replace: 'Sostituisci', category: 'Categoria', categoryPlural: 'Categorie', replaceWith: 'Sostituisci con', matching: 'Coincidenze', generalMatching: "Generale (non tiene conto delle categorie con barra)", broadMatching: "Estesa (tiene conto delle categorie con barra)", noInclude: "Non includere nella transclusione (per i template)", caseSensitive: "Tiene conto delle maiuscole e delle minuscole (solo nei modi di togliere e sostituire)", instructions: "Introduci il nome di ogni pagina che desideri categorizzare in una linea separata", outputInitial: "Qualsiasi errore trovato apparirà giù", cancel: "Annulla", addCategoryContents: "Aggiungi contenuto di categoria", initiate: "Inizia", categoryPrompt: "Per favore, introduci il nome della categoria (senza il prefisso di Categoria)", doesNotExist: "$1 non esiste", failedToGetContents: "Errore per caricare contenuti di $1", categoryAlert: "Introduci almeno una categoria", warning: "Avvertimento", closeModalWarning: "Sei sicuro che vuoi chiudere il modulo senza terminare?", close: "Chiudi", finished: "Finito", nothingLeftToDo: "Niente più di fare, o la seguente linea è in bianco", noCategoryToReplace: "Nessuna $1 per sostituire si è introdotta", pageNotExist: "La pagina $1 non esiste", addSummary: "Aggiungendo $1 (automatico)", addFail: "Errore aggiungendo $1 a $2", categoryAlready: "$1 contiene già la categoria $2 o alcun errore si è trovato; è stato omesso", categoryCheckFail: "La verificazione di categorie non è riuscita per la pagina $1; questa è stata omessa", removeNotFound: "$1 non si è trovato sulla pagina $2", removeSummary: "Rimuovendo $1 (automatico)", removeFail: "Errore rimuovendo $1 dalla pagina $2", replaceSummary: "Sostituendo $1 con $2 (automatico)", multiReplaceSummary: 'Sostituendo categorie: $1 (automatico)', removeSuccess: "$1 si è rimosso dalla pagina $2 con successo", replaceFail: "Errore sostituendo $1 sulla pagina $2", replaceSuccess: "Categoria sostituita con successo sulla pagina $1", noCategoryReplace: "Nessuna categoria per sostituire", automatic: "automatico" },		kn: { title: "ಮಾಸ್ ವರ್ಗೀಕರಣ", mode: "ಮೋಡ್", add: "ಸೇರಿಸು", remove: "ತೆಗೆದುಹಾಕು", replace: "ಬದಲಾಯಿಸಿ", category: "ವರ್ಗ", categoryPlural: "ವರ್ಗಗಳು", replaceWith: "ಬದಲಾಯಿಸಿ", matching: "ಹೊಂದಾಣಿಕೆಯ", generalMatching: "ಜನರಲ್ (ವೇಗದ ವಿಭಾಗಗಳು ಇಲ್ಲ ಖಾತೆಯನ್ನು)", broadMatching: "ಬ್ರಾಡ್ (ವೇಗದ ಕೊಂಡಿಗಳು ನೋಡಿಕೊಳ್ಳುತ್ತಾರೆ)", noInclude: "(ಟೆಂಪ್ಲೆಟ್ಗಳನ್ನು) ಸೇರ್ಪಡೆ ಸೇರಿಸಬೇಡಿ", caseSensitive: "ಕೇಸ್ ಸೂಕ್ಷ್ಮ (ತೆಗೆಯುವುದು ಮತ್ತು ಮಾತ್ರ ಬದಲಿಗೆ)", instructions: "ನೀವು ಒಂದು ಪ್ರತ್ಯೇಕ ಸಾಲಿನಲ್ಲಿ ವರ್ಗೀಕರಿಸಲು ಬಯಸುವ ಪ್ರತಿ ಪುಟದ ಹೆಸರು ಹಾಕಿ", outputInitial: "ಎದುರಿಸಿದೆ ಕೆಳಗೆ ಕಾಣಿಸುತ್ತದೆ ಯಾವುದೇ ದೋಷಗಳು", cancel: "ರದ್ದು", addCategoryContents: "ವರ್ಗದಲ್ಲಿ ವಿಷಯಗಳನ್ನು ಸೇರಿಸಿ", initiate: "ಆರಂಭಿಸು", categoryPrompt: "ದಯವಿಟ್ಟು ವರ್ಗದಲ್ಲಿ ಹೆಸರು (ಯಾವುದೇ ವರ್ಗದಲ್ಲಿ ಪೂರ್ವಪ್ರತ್ಯಯ) ನಮೂದಿಸಿ", doesNotExist: "$1 ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ", failedToGetContents: "$1 ವಿಷಯಗಳನ್ನು ಪಡೆಯಲು ವಿಫಲವಾಗಿದೆ", categoryAlert: "ದಯವಿಟ್ಟು ಒಂದು ವರ್ಗದಲ್ಲಿ ನಮೂದಿಸಿ", warning: "ಎಚ್ಚರಿಕೆ", closeModalWarning: "ನೀವು ಸ್ಥಾನ ಇಲ್ಲದೆ ಮೋಡಲ್ ಮುಚ್ಚಲು ಬಯಸಿದ್ದೀರಾ?", close: "ಮುಚ್ಚಲಾಗಿದೆ", finished: "ಮುಗಿಸಿದರು", nothingLeftToDo: "ಏನೂ ಇಲ್ಲ ಮಾಡಲು, ಅಥವಾ ಮುಂದಿನ ಸಾಲಿನ ವಿಳಾಸ", noCategoryToReplace: "ಇಲ್ಲ $1 ಪ್ರವೇಶಿಸಿತು ಬದಲಾಯಿಸಲು", pageNotExist: "ಪೇಜ್ $1 ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ", addSummary: "ಸೇರಿಸುವ $1 (ಸ್ವಯಂಚಾಲಿತ)", addFail: "$1 $2 ಸೇರಿಸಲು ವಿಫಲವಾಗಿದೆ", categoryAlready: "$1 ಈಗಾಗಲೇ ವರ್ಗದಲ್ಲಿ $2 ಅಥವಾ ದೋಷ ಕಂಡುಬಂದಿತು; ಸಾಗುವಂತೆ ಮಾಡಲಾಗಿದೆ", categoryCheckFail: "ವರ್ಗ ಚೆಕ್ $1 ವಿಫಲವಾಯಿತು; ಸಾಗುವಂತೆ ಮಾಡಲಾಗಿದೆ", removeNotFound: "$1 $2 ಕಂಡುಬಂದಿಲ್ಲ", removeFail: "$2 $1 ತೆಗೆದುಹಾಕಲು ವಿಫಲವಾಗಿದೆ", removeSuccess: "$1 $2 ಯಶಸ್ವಿಯಾಗಿ ತೆಗೆದುಹಾಕಲಾಗಿದೆ", removeSummary: "ತೆಗೆದು $1 (ಸ್ವಯಂಚಾಲಿತ)", replaceFail: "$2 $1 ಬದಲಿಗೆ ವಿಫಲವಾಗಿದೆ", replaceSuccess: "ವರ್ಗ ಯಶಸ್ವಿಯಾಗಿ $1 ಬದಲಿಗೆ", replaceSummary: "$2 (ಸ್ವಯಂಚಾಲಿತ) ಜೊತೆ ಬದಲಿಗೆ $1", multiReplaceSummary: "ವಿಭಾಗಗಳು ಬದಲಿಗೆ: $1 (ಸ್ವಯಂಚಾಲಿತ)", noCategoryReplace: "ಬದಲಿಗೆ ಯಾವುದೇ ವರ್ಗದಲ್ಲಿ", automatic: "ಸ್ವಯಂಚಾಲಿತ" },		ko: { title: "다중 분류 작업", mode: "작업", add: "추가", remove: "제거", replace: "변경", category: "분류", categoryPlural: "분류들", replaceWith: "바꿀 분류", matching: "일치 조건", generalMatching: "일반 (파이프 분류를 고려하지 않음)", broadMatching: "광역 (파이프 링크 처리)", noInclude: "틀에 매개되어 있는 분류 제외", caseSensitive: "대소문자 구분 (제거 및 변경만 가능)", instructions: "각각의 줄에 분류 작업을 할 문서 이름을 입력하십시오", outputInitial: "아래에 작업 중에 발생한 오류가 나타납니다", cancel: "취소", addCategoryContents: "분류 내용을 추가", initiate: "실행", categoryPrompt: "분류 이름을 입력하십시오 (분류 접두사 없이)", doesNotExist: "$1 문서가 이 위키에 없음", failedToGetContents: "$1 문서에서 내용을 가져오지 못함", categoryAlert: "최소 한 개의 분류를 입력하시오", warning: "경고", closeModalWarning: "정말로 이 작업을 닫으시겠습니까? 아직 작업이 끝나지 않았습니다.", close: "닫기", finished: "끝났음", nothingLeftToDo: "더 이상 할 것이 없거나 다음 줄이 비었습니다", noCategoryToReplace: "입력된 분류를 대체할 $1 문서가 없음", pageNotExist: "문서 $1 이(가) 없음", addSummary: "$1 추가 (자동)", addFail: "$2에 $1을(를) 추가하는데 실패함", categoryAlready: "$1에 이미 $2 분류가 있거나 오류가 발생함; 이 문서는 스킵됨", categoryCheckFail: "$1에서 분류를 확인하지 못함; 이 문서는 스킵됨", removeNotFound: "$2에서 $1을(를) 찾지 못함", removeFail: "$2에서 $1을(를) 제거하지 못함", removeSuccess: "$2에서 $1이(가) 성공적으로 제거됨", removeSummary: "$1 제거 (자동)", replaceFail: "$2에서 $1을(를) 바꾸지 못함", replaceSuccess: "$1(으)로 분류를 성공적으로 바꿈", replaceSummary: "$1을(를) $2(으)로 변경 (자동)", multiReplaceSummary: "분류들을 바꿈: $1 (자동)", noCategoryReplace: "바꿀 분류가 없음", automatic: "자동" },		oc: { title: 'Categorizacion en massa', mode: 'Manièra', add: 'Apondre', remove: 'Levar', replace: 'Remplaçar', category: 'Categoria', categoryPlural: 'De categorias', replaceWith: 'Remplaçar amb', matching: 'De coïncidéncias', generalMatching: "General (pren pas en compte las categorias amb barra)", broadMatching: "Vasta (pren en compte las categorias amb barra)", noInclude: "Pas inclure dins la transclusion (per de modèls)", caseSensitive: "Pren en compte de majusculas e de minúsculas (sonque en las manièras de levar e remplaçar)", instructions: "Introdusís lo nom de cada pagina que vòlguas categorizar en una linha separada", outputInitial: "Quin error trobat que siá apareisserà aval", cancel: "Anullar", addCategoryContents: "Apondre contengut de categoria", initiate: "Iniciar", categoryPrompt: "Se vos plai, introdusís lo nom de la categoria (sens lo prefixe de Categoria)", doesNotExist: "$1 existís pas", failedToGetContents: "Error al moment de cargar de contenguts de $1", categoryAlert: "Introdusís almens una categoria", warning: "Advertencia", closeModalWarning: "Ès segur que vòles barrar lo modul sens fenir?", close: "Barrar", finished: "Finalizat", nothingLeftToDo: "Brica mai per far, o la seguenta linha es en blanc", noCategoryToReplace: "Cap $1 per remplaçar s\'es introdusida", pageNotExist: "La pagina $1 existís pas", addSummary: "En apondent $1 (automatic)", addFail: "Error al moment d\'apondre $1 a $2", categoryAlready: "$1 conten ja la categoria $2 o qualque error s\'es trobat; es estat omitida", categoryCheckFail: "La verificacion de categorias manquèt per la pagina $1; aquesta es estada omitida", removeNotFound: "$1 s\'es pas trobat sus la pagina $2", removeSummary: "En levant $1 (automatic)", removeFail: "Error al moment de levar $1 de la pagina $2", replaceSummary: "En remplaçant $1 amb $2 (automatic)", multiReplaceSummary: 'En remplaçant de categorias: $1 (automatic)', removeSuccess: "$1 s\'es levat de la pagina $2 amb capitada", replaceFail: "Error al moment de remplaçar $1 sus la pagina $2", replaceSuccess: "Categoria remplaçada amb capitada sus la pagina $1", noCategoryReplace: "Cap categoria per remplaçar", automatic: "automatic" },		pl: { title: "Mass Categorization", mode: "Działanie", add: "Dodaj", remove: "Usuń", replace: "Przenieś", category: "Kategoria", categoryPlural: "Dodaj kategorie", replaceWith: "Zamień na", matching: "Dopasuj", generalMatching: "Generalnie (nie uwzględnia doprowadzonych linków)", broadMatching: "Ogólnie (bierze pod uwagę doprowadzone linki)", noInclude: "Nie należy do transkluzji (dla szablonów)", caseSensitive: "Z uwzględnieniem wielkości liter (tylko dla opcji usunięcia i przeniesienia)", instructions: "Umieść tutaj nazwę strony, jaką chcesz skategoryzować w oddzielnej linii", outputInitial: "Tutaj pojawią się wszystkie błędy", cancel: "Anuluj", addCategoryContents: "Dodaj treść do kategorii", initiate: "Uruchom", categoryPrompt: "Proszę umieścić nazwę kategorii (bez prefiksu kategorii)", doesNotExist: "$1 nie istnieje", failedToGetContents: "Nie udało się stworzyć $1", categoryAlert: "Proszę umieścić przynajmniej jedną kategorię", warning: "Ostrzeżenie", closeModalWarning: "Czy na pewno chcesz wyłączyć ten skrypt bez zapisywania żadnych kategorii?", close: "Zamknij", finished: "Zakończono", nothingLeftToDo: "Nie musisz nic robić dalej, polecenie zostało wykonane", noCategoryToReplace: "Nie możesz przenieść strony $1", pageNotExist: "Strona $1 nie istnieje", addSummary: "Dodano $1 (automatycznie)", addFail: "Nie udało się dodać $1 do $2", categoryAlready: "$1 posiada już kategorię $2 lub mógł wystąpić błąd, procedura została pominięta", categoryCheckFail: "Kategoria nie sprawdziła się na stronie $1; została pominięta", removeNotFound: "$1 nie zostało znalezione na $2", removeFail: "Nie udało się usunąć $1 z $2", removeSuccess: "$1 zostało usunąć z $2", removeSummary: "Usunięto $1 (automatycznie)", replaceFail: "Nie udało się przenieść $1 na $2", replaceSuccess: "Kategoria pomyślnie przeniesiona na $1", replaceSummary: "Zamieniono $1 z $2 (automatycznie)", multiReplaceSummary: "Przeniesienie kategorii: $1 (automatycznie)", noCategoryReplace: "Nie ma kategorii do przeniesienia", automatic: "automatycznie" },		pt: { title: 'Categorização em massa', mode: 'Modo', add: 'Acrescentar', remove: 'Tirar', replace: 'Substituir', category: 'Categoria', categoryPlural: 'Categorias', replaceWith: 'Substituir com', matching: 'Coincidências', generalMatching: "Geral (sem ter em consideração as categorias com barra)", broadMatching: "Extensa (tendo em consideração as categorias com barra)", noInclude: "Não incluir na transclusão (para predefinições)", caseSensitive: "Ter em consideração maiúsculas e minúsculas (só nos modos de tirar e substituir)", instructions: "Introduz o nome de cada página que quiseres categorizar numa linha separada", outputInitial: "Qualquer erro encontrado aparecerá abaixo", cancel: "Cancelar", addCategoryContents: "Acrescentar conteúdo de categoria", initiate: "Iniciar", categoryPrompt: "Por favor, introduz o nome da categoria (sem o prefixo de Categoria)", doesNotExist: "$1 não existe", failedToGetContents: "Erro ao carregar conteúdos de $1", categoryAlert: "Introduz ao menos uma categoria", warning: "Advertência", closeModalWarning: "Tens a certeza de que queres fechar o módulo sem terminares?", close: "Fechar", finished: "Finalizado", nothingLeftToDo: "Mais nada para fazeres, ou a seguinte linha está em branco", noCategoryToReplace: "Nenhuma $1 para substituir foi introduzida", pageNotExist: "A página $1 não existe", addSummary: "A acrescentar $1 (automático)", addFail: "Erro ao acrescentar $1 a $2", categoryAlready: "$1 já contém a categoria $2 ou algum erro foi encontrado; então foi omitido", categoryCheckFail: "A verificação de categorias falhou para a página $1; então foi omitida", removeNotFound: "$1 não se encontrou na página $2", removeSummary: "A remover $1 (automático)", removeFail: "Erro ao remover $1 da página $2", replaceSummary: "A substituir $1 com $2 (automático)", multiReplaceSummary: 'A substituir categorias: $1 (automático)', removeSuccess: "$1 removeu-se da página $2 com sucesso", replaceFail: "Erro ao substituir $1 na página $2", replaceSuccess: "Categoria substituída com sucesso na página $1", noCategoryReplace: "Nenhuma categoria para substituir", automatic: "automático" },		'pt-br': { title: 'Categorização em massa', mode: 'Modo', add: 'Adicionar', remove: 'Remover', replace: 'Substituir', category: 'Categoria', categoryPlural: 'Categorias', replaceWith: 'Substituir com', matching: 'Coincidências', generalMatching: "General (sem levar em conta as categorias com barra)", broadMatching: "Extensa (levando em conta as categorias com barra)", noInclude: "Não incluir na transclusão (para predefinições)", caseSensitive: "Levando em conta maiúsculas e minúsculas (só nos modos de remover e substituir)", instructions: "Introduza o nome da cada página que você quiser categorizar em uma linha separada", outputInitial: "Qualquer erro encontrado aparecerá embaixo", cancel: "Anular", addCategoryContents: "Adicione conteúdo de categoria", initiate: "Iniciar", categoryPrompt: "Por favor, introduza o nome da categoria (sem o prefixo de Categoria)", doesNotExist: "$1 não existe", failedToGetContents: "Erro carregando conteúdos de $1", categoryAlert: "Introduza ao menos uma categoria", warning: "Advertência", closeModalWarning: "Tem certeza que você quer fechar o módulo sem terminar?", close: "Fechar", finished: "Finalizado", nothingLeftToDo: "Nada mais para fazer, ou a seguinte linha está em branco", noCategoryToReplace: "Nenhuma $1 para substituir foi introduzida", pageNotExist: "A página $1 não existe", addSummary: "Adicionando $1 (automático)", addFail: "Erro adicionando $1 a $2", categoryAlready: "$1 já contém a categoria $2 ou algum erro foi encontrado; ele foi ignorado", categoryCheckFail: "A verificação de categorias falhou para a página $1; ela foi ignorada", removeNotFound: "$1 não foi encontrado na página $2", removeSummary: "Removendo $1 (automático)", removeFail: "Erro removendo $1 da página $2", replaceSummary: "Substituindo $1 com $2 (automático)", multiReplaceSummary: 'Substituindo categorias: $1 (automático)', removeSuccess: "$1 foi removido da página $2 com sucesso", replaceFail: "Erro substituindo $1 na página $2", replaceSuccess: "Categoria substituída com sucesso na página $1", noCategoryReplace: "Nenhuma categoria para substituir", automatic: "automático" },		ro: { title: 'Categorisirea masivă', mode: 'Mod', add: 'Adăugare', remove: 'Eliminare', replace: 'Înlocuire', category: 'Categorie', categoryPlural: 'Categorii', replaceWith: 'Înlocuieşte cu', matching: 'Coincidenţe', generalMatching: "General (nu ia în considerare categoriile cu bară)", broadMatching: "Largă (luând în considerare categoriile cu bară)", noInclude: "Nu include în includerea formatului (pentru formate)", caseSensitive: "Luând în considerare majuscule şi minuscule (doar în modurile de eliminare şi înlocuire)", instructions: "Introdu numele fiecărui pagini pe care vrei să-o categorizezi într-o linie separa", outputInitial: "Orice eroare găsită va apărea jos", cancel: "Revocare", addCategoryContents: "Adăugarea conţinutului de categorie", initiate: "Început", categoryPrompt: "Te rugam să introduci numele categoriei (fără prefixul de Categorie)", doesNotExist: "$1 nu există", failedToGetContents: "Eroare pentru a încărca conţinutul de $1", categoryAlert: "Introdu cel puţin o categorie", warning: "Avertisment", closeModalWarning: "Eşti sigur că vrei să închizi modulul fără să termini?", close: "Închidere", finished: "Finalizat", nothingLeftToDo: "Nimic altceva de făcut, sau următoarea linie este goală", noCategoryToReplace: "Nicio $1 pentru a înlocui s-a introdus", pageNotExist: "Pagina $1 nu există", addSummary: "Adăugând $1 (automatic)", addFail: "Eroare pentru a adăuga $1 la $2", categoryAlready: "$1 deja conţine categoria $2 sau vreo eroare s-a găsit; a fost omisă", categoryCheckFail: "Verificarea categoriilor a ratat pentru pagina $1; aceasta a fost omisă", removeNotFound: "$1 nu s-a găsit pe pagina $2", removeSummary: "Scoţând $1 (automatic)", removeFail: "Eroare scoţând $1 din pagina $2", replaceSummary: "Înlocuind $1 cu $2 (automatic)", multiReplaceSummary: 'Înlocuind categorii: $1 (automatic)', removeSuccess: "$1 s-a scos din pagina $2 cu succes", replaceFail: "Erori înlocuind $1 pe pagina $2", replaceSuccess: "Categorii înlocuite cu succes -pe pagina $1", noCategoryReplace: "Nicio categorie pentru a înlocui", automatic: "automatic" },		ru: { title: "Массовая категоризация", mode: "Действие", add: "Добавить", remove: "Удалить", replace: "Переместить", category: "Категория", categoryPlural: "Категории", replaceWith: "Заменить на", matching: "Сравнение", generalMatching: "Обычное (не учитывает отдельные категории)", broadMatching: "Расширенное (учитывает отдельные ссылки)", noInclude: "Не учитывать включения (для шаблонов)", caseSensitive: "С учётом регистра (только для опций удаления и перемещения)", instructions: "Разместите здесь название страницы, которую вы хотите поместить в категорию в отдельной строке", outputInitial: "Здесь будут появляться все ошибки", cancel: "Отмена", addCategoryContents: "Добавить содержимое категории", initiate: "Запустить", categoryPrompt: "Пожалуйста, укажите название категории (без префикса Категория:)", doesNotExist: "$1 не существует", failedToGetContents: "Не удалось создать $1", categoryAlert: "Пожалуйста, поставьте хотя бы одну категорию", warning: "Предупреждение", closeModalWarning: "Вы уверены, что хотите отключить этот скрипт без сохранения каких-либо категорий?", close: "Закрыть", finished: "Завершено", nothingLeftToDo: "Вам не нужно ничего делать дальше или следующая строка пустая", noCategoryToReplace: "Вы не можете переместить страницы $1", pageNotExist: "Страница $1 не существует", addSummary: "Добавлено $1 (автоматически)", addFail: "Не удалось добавить $1 в $2", categoryAlready: "$1 уже в категории $2 или произошла ошибка, данное название было пропущено", categoryCheckFail: "Категория $1 не найдена; данное название было пропущено", removeNotFound: "$1 не было найдено в $2", removeFail: "Не удалось удалить $1 из $2", removeSuccess: "$1 было удалено из $2", removeSummary: "Удалено из $1 (автоматически)", replaceFail: "Не удалось заменить $1 на $2", replaceSuccess: "Категория успешно заменена на $1", replaceSummary: "Замена $1 на $2 (автоматически)", multiReplaceSummary: "Замена категорий: $1 (автоматически)", noCategoryReplace: "Нет категории для замены", automatic: "автоматически" },		uk: { title: "Масова категоризація", mode: "Дія", add: "Додати", remove: "Видалити", replace: "Перемістити", category: "Категорія", categoryPlural: "Категорії", replaceWith: "Замінити на", matching: "Порівняння", generalMatching: "Звичайне (не враховує окремі категорії)", broadMatching: "Розширене (враховує окремі посилання)", noInclude: "Не враховувати включення (для шаблонів)", caseSensitive: "З урахуванням регістра (тільки для опцій видалення та переміщення)", instructions: "Розмістіть тут назву сторінки, яку ви хочете помістити у категорію в окремому рядку", outputInitial: "Тут з\'являтимуться всі помилки", cancel: "Скасування", addCategoryContents: "Додати вміст категорії", initiate: "Запустити", categoryPrompt: "Будь ласка, вкажіть назву категорії (без префікса Категорія:)", doesNotExist: "$1 не існує", failedToGetContents: "Не вдалося створити $1", categoryAlert: "Будь ласка, поставте хоча б одну категорію", warning: "Попередження", closeModalWarning: "Ви впевнені, що хочете відключити цей скрипт без збереження будь-яких категорій?", close: "Закрити", finished: "Завершено", nothingLeftToDo: "Вам не потрібно нічого робити далі або наступний рядок порожний", noCategoryToReplace: "Ви не можете перемістити сторінки $1", pageNotExist: "Сторінка $1 не існує", addSummary: "Додано $1 (автоматично)", addFail: "Не вдалося додати $1 до $2", categoryAlready: "$1 вже в категорії $2 або сталася помилка, цю назву було пропущено", categoryCheckFail: "Категорія $1 не знайдена; цю назву було пропущено", removeNotFound: "$1 не було знайдено в $2", removeFail: "Не вдалося видалити $1 з $2", removeSuccess: "$1 було видалено з $2", removeSummary: "Видалено з $1 (автоматично)", replaceFail: "Не вдалося замінити $1 на $2", replaceSuccess: "Категорію успішно замінено на $1", replaceSummary: "Заміна $1 на $2 (автоматично)", multiReplaceSummary: "Заміна категорій: $1 (автоматично)", noCategoryReplace: "Немає категорії для заміни", automatic: "автоматично" },		val: { title: 'Categorisació en massa', mode: 'Modo', add: 'Afegir', remou: 'Traure', replace: 'Reemplaçar', category: 'Categoria', categoryPlural: 'Categories', replaceWith: 'Reemplaçar en', matching: 'Coincidències', generalMatching: "General (no pren en conte les categories en barra)", broadMatching: "Extensa (prenent en conte les categories en barra)", noInclude: "No incloure en transclusió (per a plantilles)", caseSensitive: "Prenent en conte mayúscules i minúscules (només en els modos de traure i reemplaçar)", instructions: "Introduix el nom de cada pàgina que voleres categorisar en una llínia separada", outputInitial: "Qualsevol error trobat apareixerà avall", cancell: "Cancelar", addCategoryContents: "Afegir contingut de categoria", initiate: "Iniciar", categoryPrompt: "Per favor, introduix el nom de la categoria (sense el prefix de Categoria)", doesNotExist: "$1 no existix", failedToGetContents: "Error carregant continguts de $1", categoryAlert: "Introduix al menys una categoria", warning: "Advertència", closeModalWarning: "¿Estàs segur de que vols tancar el mòdul sense terminar?", close: "Tancar", finished: "Finalisat", nothingLeftToDo: "Res més que fer, o la següent llínia està en blanc", noCategoryToReplace: "Cap $1 per a reemplaçar s\'ha introduït", pageNotExist: "La pàgina $1 no existix", addSummary: "Afegint $1 (automàtic)", addFail: "Error afegint $1 a $2", categoryAlready: "$1 ya conté la categoria $2 o algun error s\'ha trobat; ha segut omesa", categoryCheckFail: "La verificació de categories fallà per a la pàgina $1; esta ha segut omesa", removeNotFound: "$1 no s\'ha trobat en la pàgina $2", removeSummary: "Traient $1 (automàtic)", removeFail: "Erro traient $1 de la pàgina $2", replaceSummary: "Reemplaçant $1 en $2 (automàtic)", multiReplaceSummary: 'Reemplaçant categories: $1 (automàtic)', removeSuccess: "$1 s\'ha tret de la pàgina $2 en èxit", replaceFail: "Error reemplaçant $1 en la pàgina $2", replaceSuccess: "Categoria reemplaçada en èxit en la pàgina $1", noCategoryReplace: "Cap categoria per a reemplaçar", automatic: "automàtic" },		vi: { title: "Phân loại tập trung", mode: "Chế độ", add: "Thêm", remove: "Loại bỏ", replace: "Thay thế", category: "Thể loại", categoryPlural: "Các thể loại", replaceWith: "Thay thế với", matching: "Kết hợp", generalMatching: "Bình thường (không tính những đường dẫn...) /* Need proper translation */", broadMatching: "Rộng (takes care of piped links...) /* Need proper translation */", noInclude: "Do not include in transclusion (for templates)", caseSensitive: "Phân biệt hoa/thường (chỉ đối với loại bỏ/thay thế)", instructions: "Cho tên của từng trang bạn muốn phân loại vào từng dòng riêng lẻ một.", outputInitial: "Bất kì lỗi nào bạn gặp phải sẽ được xuất hiện dưới đây", cancel: "Thoát", addCategoryContents: "Thêm nội dung của thể loại", initiate: "Bắt đầu", categoryPrompt: "Làm ơn thêm tên thể loại (không có tiền tố)", doesNotExist: "$1 không tồn tại", failedToGetContents: "Thất bại trong việc lấy nội dung của $1", categoryAlert: "Xin hãy điền ít nhất một thể loại", warning: "Cảnh báo!", closeModalWarning: "Bạn có muốn đóng phương thức này mà không hoàn thành hay không??", close: "Đóng", finished: "Đã hoàn thành", nothingLeftToDo: "Không còn việc gì để làm, hoặc dòng tiếp theo trống", noCategoryToReplace: "Không có $1 để thay thế với thứ đã được nhập", pageNotExist: "Trang $1 không tồn tại", addSummary: "Đang thêm $1 (tự động)", addFail: "Thất bại trong việc thêm $1 vào $2", categoryAlready: "$1 đã sẵn có trong thể loại $2 hoặc đã gặp lỗi; đã bỏ qua", categoryCheckFail: "Kiểm tra thể loại cho $1 thất bại; đã bỏ qua", removeNotFound: "$1 không tìm thấy trong $2", removeFail: "Thất bại trong việc loại bỏ $1 khỏi $2", removeSuccess: "$1 đã được loại bỏ khỏi $2", removeSummary: "Đang loại bỏ $1 (tự động)", replaceFail: "Thất bại trong việc thay thế $1 với $2", replaceSuccess: "Thể loại đã được thay thế bởi $1", replaceSummary: "Đang thay thế $1 với $2 (tự động)", multiReplaceSummary: "Đang thay thế thể loại: $1 (tự động)", noCategoryReplace: "Không có thể loại để thay thế", automatic: "tự động" },		zh: { title: "批次分类", mode: "模式", add: "添加", remove: "移除", replace: "取代", category: "分类", categoryPlural: "分类", replaceWith: "取代为", matching: "配对中", generalMatching: "一般（将不处理含有管道链接的分类 (Piped category)）", broadMatching: "广泛（一并处理管道链接 (Piped link)）", noInclude: "不包含透过模板嵌入的分类", caseSensitive: "区分大小写（仅用于移除及取代）", instructions: "请逐行输入各个您想要分类的页面名称", outputInitial: "任何出现的错误会显示于下方", cancel: "取消", addCategoryContents: "添加分类内容", initiate: "开始", categoryPrompt: "请输入分类名称（不含前缀字，即「Category:」或「分类:」）", doesNotExist: "$1 不存在", failedToGetContents: "无法取得 $1 的内容", categoryAlert: "请输入至少一个分类", warning: "警告", closeModalWarning: "确定要在尚未完成操作的情况下关闭此窗口吗？", close: "关闭", finished: "已完成", nothingLeftToDo: "已无需处理的项目，或下一行为空白", noCategoryToReplace: "输入内容中找不到取代项目 $1", pageNotExist: "页面 $1 不存在", addSummary: "正在添加 $1（自动）", addFail: "添加 $1 至 $2 失败", categoryAlready: "页面 $1 已有分类 $2，或出现错误. 已略过", categoryCheckFail: "检查于 $1 的分类失败. 已略过", removeNotFound: "于 $2 找不到 $1", removeFail: "自 $2 移除 $1 失败", removeSuccess: "成功自 $2 移除 $1", removeSummary: "正在移除 $1（自动）", replaceFail: "于 $2 取代 $1 失败 (Failed to replace $1 on $2)", replaceSuccess: "成功取代页面 $1 中的分类", replaceSummary: "正在取代 $1 为 $2（自动）", multiReplaceSummary: "正在取代分类：$1（自动）", noCategoryReplace: "没有可取代的分类", automatic: "自动" },		'zh-hant': { title: "批次分類", mode: "模式", add: "添加", remove: "移除", replace: "取代", category: "分類", categoryPlural: "分類", replaceWith: "取代為", matching: "配對中", generalMatching: "一般（將不處理含有管道鏈接的分類 (Piped category)）", broadMatching: "廣泛（一併處理管道鏈接 (Piped link)）", noInclude: "不包含透過模板嵌入的分類", caseSensitive: "區分大小寫（僅用於移除及取代）", instructions: "請逐行輸入各個您想要分類的頁面名稱", outputInitial: "任何出現的錯誤會顯示於下方", cancel: "取消", addCategoryContents: "添加分類內容", initiate: "開始", categoryPrompt: "請輸入分類名稱（不含前綴字，即「Category:」或「分類:」）", doesNotExist: "$1 不存在", failedToGetContents: "無法取得 $1 的內容", categoryAlert: "請輸入至少一個分類", warning: "警告", closeModalWarning: "確定要在尚未完成操作的情況下關閉此視窗嗎？", close: "關閉", finished: "已完成", nothingLeftToDo: "已無需處理的項目，或下一行為空白", noCategoryToReplace: "輸入內容中找不到取代項目 $1", pageNotExist: "頁面 $1 不存在", addSummary: "正在添加 $1（自動）", addFail: "添加 $1 至 $2 失敗", categoryAlready: "頁面 $1 已有分類 $2，或出現錯誤. 已略過", categoryCheckFail: "檢查於 $1 的分類失敗. 已略過", removeNotFound: "於 $2 找不到 $1", removeFail: "自 $2 移除 $1 失敗", removeSuccess: "成功自 $2 移除 $1", removeSummary: "正在移除 $1（自動）", replaceFail: "於 $2 取代 $1 失敗 (Failed to replace $1 on $2)", replaceSuccess: "成功取代頁面 $1 中的分類", replaceSummary: "正在取代 $1 為 $2（自動）", multiReplaceSummary: "正在取代分類：$1（自動）", noCategoryReplace: "沒有可取代的分類", automatic: "自動" },		'zh-tw': { title: "批次分類", mode: "模式", add: "新增", remove: "移除", replace: "取代", category: "分類", categoryPlural: "分類", replaceWith: "取代為", matching: "配對中", generalMatching: "一般（將不處理含有管道連結的分類 (Piped category)）", broadMatching: "廣泛（一併處理管道連結 (Piped link)）", noInclude: "不包含透過模板嵌入的分類", caseSensitive: "區分大小寫（僅用於移除及取代）", instructions: "請逐行輸入各個您想要分類的頁面名稱", outputInitial: "任何出現的錯誤會顯示於下方", cancel: "取消", addCategoryContents: "新增分類內容", initiate: "開始", categoryPrompt: "請輸入分類名稱（不含前綴字，即「Category:」或「分類:」）", doesNotExist: "$1 不存在", failedToGetContents: "無法取得 $1 的內容", categoryAlert: "請輸入至少一個分類", warning: "警告", closeModalWarning: "確定要在尚未完成操作的情況下關閉此視窗嗎？", close: "關閉", finished: "已完成", nothingLeftToDo: "已無需處理的項目，或下一行為空白", noCategoryToReplace: "輸入內容中找不到取代項目 $1", pageNotExist: "頁面 $1 不存在", addSummary: "正在新增 $1（自動）", addFail: "新增 $1 至 $2 失敗", categoryAlready: "頁面 $1 已有分類 $2，或出現錯誤. 已略過", categoryCheckFail: "檢查於 $1 的分類失敗. 已略過", removeNotFound: "於 $2 找不到 $1", removeFail: "自 $2 移除 $1 失敗", removeSuccess: "成功自 $2 移除 $1", removeSummary: "正在移除 $1（自動）", replaceFail: "於 $2 取代 $1 失敗 (Failed to replace $1 on $2)", replaceSuccess: "成功取代頁面 $1 中的分類", replaceSummary: "正在取代 $1 為 $2（自動）", multiReplaceSummary: "正在取代分類：$1（自動）", noCategoryReplace: "沒有可取代的分類", automatic: "自動" }		//language list - stop };	//set i18n according to user's language i18n = i18n[mw.config.get("wgUserLanguage")] || i18n[mw.config.get("wgUserLanguage").split('-')[0]] || i18n.en; var categoryName = mw.config.get('wgFormattedNamespaces')[14]; var FormMC = '\ <form method="" name="" class="WikiaForm "> \ \           ' + i18n.mode + ': \ <select id="select-mc"> \ ' + i18n.add + ' \ ' + i18n.remove + ' \ ' + i18n.replace + ' \ \           \            \                + \ \                - \            \            \                ' + i18n.category + ': \ <input type="text" class="category-name" value="" /> \ <p class="replace-para" style="display: none; padding-top: 3px;">' + i18n.replaceWith+ ': \ <input type="text" class="replace-category-name" value="" /> \ \               ' + i18n.matching + ': \ \               <label for="normal-removal"><input type="radio" id="mc-normal-removal" name="mass-categorization-removal" value="1" checked="checked"/>' + i18n.generalMatching + ' \ \               <label for="broad-removal"><input type="radio" id="mc-broad-removal" name="mass-categorization-removal"/ value="2">' + i18n.broadMatching + ' \ \           \                <label for="no-include"><input type="checkbox" id="mc-noinclude" name="mass-categorization-noinclude"/ value="1">' + i18n.noInclude + ' \ \               <label for="case-sensitive"><input type="checkbox" id="mc-case-sensitive" name="mass-categorization-casesensitive"/ value="1">' + i18n.caseSensitive + ' \ \           \            ' + i18n.instructions + ' \ <textarea style="height: 20em; width: 80%;" id="text-categorization"/> \ \       ' + i18n.outputInitial + ' \   ',    delay = window.massCategorizationDelay || 1000, Api = new mw.Api; function click { $.showCustomModal(i18n.title, FormMC, {           id: 'form-categorization',            callback: function {                document.getElementById('mc-add-category').addEventListener('click', function(e) { e.preventDefault; document.getElementById('mc-remove-category').removeAttribute('disabled'); var container = document.getElementById('mc-categories-container'); $(container).append(' \                       ' + i18n.category + ': \                            <input type="text" class="category-name" value="" /> \                        <p class="replace-para" style="' + (document.getElementById('select-mc').value == 3 ? '' : 'display: none;') + 'padding-top: 3px;">' + i18n.replaceWith + ': \                            <input type="text" class="replace-category-name" value="" />\                    '); $(container.lastElementChild).fadeIn; });               document.getElementById('mc-remove-category').addEventListener('click', function(e) { e.preventDefault; var $toremove = $('#mc-categories-container > div:not(.removed)').last; $toremove.addClass('removed').fadeOut(400, function {                       $(this).remove;                    }); if ($toremove.parent.children(':not(.removed):last').prop('tagName') != 'DIV') this.setAttribute('disabled', 'disabled'); });               document.getElementById('select-mc').addEventListener('change', function { if (this.value == 3) { $('.replace-para').fadeIn; } else { $('.replace-para').fadeOut; }               });            },            width: 500,            buttons: [{                message: i18n.cancel,                handler: function {                    $('#form-categorization').closeModal;                }            }, {                message: i18n.addCategoryContents,                defaultButton: true,                handler: addCategoryContents            }, {                id: 'start-button',                message: i18n.initiate,                defaultButton: true,                handler: init            }]        }); }   $('#my-tools-menu').prepend(        $('', { 'class': 'custom' }).append( $('', {               id: 't-mc',                text: i18n.title,                click: click            }) )   );    function logError(msg) { console.log(msg); var errBox = document.getElementById('text-error-output'); var text = document.createTextNode(msg); errBox.appendChild(text); var brTag = document.createElement('br'); errBox.appendChild(brTag); }   function addCategoryContents { var category = prompt(i18n.categoryPrompt + ' :').replace('_', ' '); Api.get({               action: 'query',                list: 'categorymembers',                cmtitle: i18n.category + ':' + category,                cmlimit: 5000,                cb: new Date.getTime            }) .done(function(d) {               if (!d.error) {                    var data = d.query;                    var pList = document.getElementById('text-categorization');                    if (data.categorymembers) {                        for (var i in data.categorymembers) {                            pList.value += data.categorymembers[i].title + '\n';                        }                    } else {                        logError(i18n.doesNotExist.replace('$1',category));                    }                } else {                    logError(i18n.failedToGetContents.replace('$1',category) + ' : ' + d.error.code);                }            }) .fail(function {               logError(i18n.failedToGetContents.replace('$1',category));            }); }   function init { var catSlots = Array.from(document.getElementsByClassName('category-name')), txt = document.getElementById('text-categorization'), pages = txt.value.split('\n'), page = pages[0], catNames = []; $.each(catSlots, function(i, name) {           name = name.value.trim;            catNames.push(name.charAt(0).toUpperCase + name.slice(1));        }); if (!catNames.filter(Boolean).length) { alert(i18n.categoryAlert); return; }       document.getElementById('start-button').setAttribute('disabled', 'disabled'); $('.blackout, #form-categorization .close').unbind; $('.blackout, #form-categorization .close').bind('click', function {           $.showCustomModal(i18n.warning, i18n.closeModalWarning, { id: 'close-warning', width: 400, buttons: [{ message: i18n.close, defaultButton: true, handler: function { // Nope, you can't close both with one call. $('#close-warning').closeModal; $('#form-categorization').closeModal; }               }, {                    message: i18n.cancel, handler: function { $('#close-warning').closeModal; }               }]            });        });        if (!page && !document.getElementById('form-complete')) { document.getElementById('start-button').removeAttribute("disabled"); $.showCustomModal(i18n.finished, i18n.nothingLeftToDo, {               id: 'form-complete',                width: 200,                callback: function {                    var $blackout = $('.blackout').last;                    $blackout.unbind;                    $blackout.click(function { $('#form-complete .wikia-button').click; });               },                buttons: [{                    message: i18n.close,                    id: 'form-complete-button',                    defaultButton: true,                    handler: function {                        $('#form-complete').closeModal;                        var $elems = $('.blackout, #form-categorization .close');                        $elems.unbind;                        $elems.click(function { $('#form-categorization').closeModal; });                   }                }]            });        } else { categorize(page, catNames); }       pages = pages.slice(1, pages.length); txt.value = pages.join('\n'); }   function categorize(pageToCat, cats) { var actionVal = document.getElementById('select-mc').value; if (actionVal == 3) { var newCatEl = Array.from(document.getElementsByClassName('replace-category-name')); var newCats = []; $.each(newCatEl, function(i, name) {               name = name.value.trim;                newCats.push(name.charAt(0).toUpperCase + name.slice(1));            }); if (!newCats.filter(Boolean).length) { alert(i18n.noCategoryToReplace.replace('$1', (newCatEl.length == 1 ? i18n.category : i18n.categoryPlural) )); document.getElementById('start-button').removeAttribute("disabled"); return; }       }        Api.get({            action: 'query',            titles: pageToCat,            prop: 'revisions|categories',            rvprop: 'content',            cb: new Date.getTime        }).done(function(d) {            var page = d.query.pages[Object.keys(d.query.pages)[0]];            var content = page.missing ===  ?  : page.revisions[0]['*'];            var newContent = content;            var config;            var summary;            if (actionVal == 1 && !d.error) {                /*                 * Add category.                 */                if (page.missing === '') {                    logError(i18n.pageNotExist.replace('$1', pageToCat));                    return;                }                var knownCats = [];                if (page.categories) {                    $.each(page.categories, function(i, categ) { knownCats.push(categ.title); });               }                var toAdd = [];                $.each(cats, function(i, cat) { if (!cat) return; cat = i18n.category + ':' + cat; if (knownCats.indexOf(cat) === -1) toAdd.push(cat); });               if (toAdd.length) {                    var sPrefix = "";                    var sSuffix = "";                    if ($('input[name=mass-categorization-noinclude]').prop('checked')) {                        sPrefix = " ";                        sSuffix = "<\/noinclude>";                    }                    summary = i18n.addSummary                        .replace('$1', (toAdd.length == 1 ? i18n.category : i18n.categoryPlural + ':') + ' ' + toAdd.join(', ') + )                        .replace(new RegExp('\\[\\[(?:' + i18n.category + '|Category):(.*?)\\]\\]', 'gi'), '$1');                    config = {                        format: 'json',                        action: 'edit',                        title: pageToCat,                        summary: summary,                        nocreate: ,                        appendtext: sPrefix + '\n' + toAdd.join('\n') + '' + sSuffix, bot: true, minor: true, token: mw.user.tokens.get('editToken') };                   $.ajax({                        url: mw.util.wikiScript('api'),                        data: config,                        dataType: 'json',                        type: 'POST',                        success: function(d) {                            if (!d.error) {                                console.log((toAdd.length == 1 ? i18n.category : i18n.categoryPlural) + ' successfully added to ' + pageToCat + '!');                            } else {                                logError(i18n.addFail.replace('$1',(toAdd.length == 1 ? i18n.category : i18n.categoryPlural )).replace('$2',pageToCat) + ': ' + d.error.code);                           }                        },                        error: function {                            logError(i18n.addFail.replace('$1',(toAdd.length == 1 ? i18n.category : i18n.categoryPlural )).replace('$2',pageToCat));                       }                    }); } else { logError(cats.length == 1 ? pageToCat + ' already has the category ' + cats[0].substring(9) + ' or an error was encountered; it has been skipped.' : pageToCat + ' has each of the categories specified; it has been skipped.'); }           } else if (actionVal == 2 && !d.error) { /*                * Remove category. */               if (page.missing === '') { logError(i18n.pageNotExist.replace('$1',pageToCat)); return; }               $.each(cats, function(i, cat) {                    if (!cat) {                        cats[i] = false;                        return;                    }                    // Remove it                    var cSens = document.getElementById('mc-case-sensitive').checked;                    var broad = document.getElementById('mc-broad-removal').checked;                    var flags = 'g' + (cSens ? '' : 'i');                   var escapedCat = $.escapeRE(cat).replace(/\s/g, '(\\s|_)');                    var escapedName = $.escapeRE(categoryName).replace(/\s/g, '(\\s|_)');                    var nRegEx = '\\[\\[' + escapedName + ':' + escapedCat + '\\]\\]';                    var sRegEx = '(\\[\\[' + escapedName + ':' + escapedCat + '\\]\\]|\\[\\[' + i18n.category + ':' + escapedCat + '\\|.*?\\]\\])';                    var regex = new RegExp(broad ? sRegEx : nRegEx, flags);                   if ($('input[name=mass-categorization-removal]:checked').val == 2) {                        regex = new RegExp(sRegEx, "gi");                    }                    if (document.getElementById('mc-noinclude').checked) {                        regex = new RegExp('\\<noinclude\\>\\s*' + (broad ? sRegEx : nRegEx) + '\\s*\\<\/noinclude\\>', flags);                    }                    if (regex.test(newContent))                         newContent = newContent.replace(regex, );                    else {                        console.log(i18n.removeNotFound.replace('$1', cat).replace('$2', pageToCat));                        cats[i] = false;                    }                    newContent = newContent.replace(regex, );                }); //don't submit if new and old contents are equal (no category found) if (newContent == content) { logError(i18n.removeNotFound.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2',pageToCat )); return; }               //submit new page cats = cats.filter(Boolean); summary = i18n.removeSummary .replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) + ' ' + i18n.category + ':' + cats.join(', ' + i18n.category + ':') + '') .replace(new RegExp('\\[\\[(?:' + i18n.category + '|Category):(.*?)\\]\\]', 'gi'), '$1'); config = { format: 'json', action: 'edit', watchlist: 'nochange', title: pageToCat, summary: summary, nocreate: '', text: newContent, bot: true, minor: true, token: mw.user.tokens.get('editToken') };               $.ajax({                    url: mw.util.wikiScript('api'),                    data: config,                    dataType: 'json',                    type: 'POST',                    success: function(d) {                        if (!d.error) {                            console.log(i18n.removeSuccess.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat) );                       } else {                            logError(i18n.removeFail.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat) + ': ' + d.error.code);                       }                    },                    error: function {                        logError(i18n.removeFail.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat));                   }                }); } else if (actionVal == 3 && !d.error) { /*                 * Replace category. */               if (page.missing === '') { logError(i18n.pageNotExist.replace('$1', pageToCat) ); return; }               // Replace it                $.each(cats, function(i, cat) {                    if (!cat) {                        console.log(i18n.noCategoryToReplace);                        cat[i] = false;                        newCats[i] = false;                        return;                    } else if (!newCats[i]) {                        console.log(cat + ': ' + i18n.noCategoryToReplace);                        cats[i] = false;                        newCats[i] = false;                        return;                    }                    var cSens = document.getElementById('mc-case-sensitive').checked;                    var broad = document.getElementById('mc-broad-removal').checked;                    var flags = 'g' + (cSens ? '' : 'i');                   var escapedCat = cat;                    ['\\', '(', ')', '[', ']', '{', '}', '?', '.', '^', '$', '|'].forEach(function(el) { escapedCat = escapedCat.replace(new RegExp('\\' + el, 'g'), '\\' + el); });                   var nRegEx = '\\[\\[' + i18n.category + ':' + escapedCat + '\\]\\]';                    var sRegEx = '(\\[\\[' + i18n.category + ':' + escapedCat + '\\]\\]|\\[\\[' + i18n.category + ':' + escapedCat + '\\|.*?\\]\\])';                    var regex = new RegExp(broad ? sRegEx : nRegEx, flags);                   var newCat = i18n.category + ':' + newCats[i].charAt(0).toUpperCase + newCats[i].substring(1);                    if (regex.test(newContent))                         newContent = newContent.replace(regex,  + newCat + );                    else {                        cats[i] = false;                        newCats[i] = false;                        return;                    }                }); // Don't submit if new and old contents are equal (no category found) if (newContent == content) { logError(i18n.removeNotFound.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat)); return; }               // Create the summary cats = cats.filter(Boolean); newCats = newCats.filter(Boolean); if (cats.length == 1) summary = i18n.replaceSummary .replace('$1',  + cats[0] + ) .replace('$2',  + newCats[0] + ); else { var replacements = ''; $.each(cats, function(i, cat) {                       var temp = replacements + '' + cat + ' → ' + newCats[i] + ', ';                        if (temp.length > 150) {                            if (replacements.indexOf('(+)') == -1)                                replacements = replacements.replace('(' + i18n.automatic + ')', '(+) (' + i18n.automatic + ')');                            return;                        }                        replacements = temp;                    }); summary = i18n.multiReplaceSummary .replace('$1', replacements.slice(0, replacements.length - 2)); }               //submit new page config = { format: 'json', action: 'edit', watchlist: 'nochange', title: pageToCat, summary: summary, nocreate: '', text: newContent, bot: true, minor: true, token: mw.user.tokens.get('editToken') };               $.ajax({                    url: mw.util.wikiScript('api'),                    data: config,                    dataType: 'json',                    type: 'POST',                    success: function(d) {                        if (!d.error) {                            console.log(i18n.replaceSuccess.replace('$1', pageToCat));                        } else {                            logError(i18n.replaceFail.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat) + ': ' + d.error.code);                       }                    },                    error: function {                        logError(i18n.replaceFail.replace('$1', (cats.length == 1 ? i18n.category : i18n.categoryPlural) ).replace('$2', pageToCat));                   }                }); } else { if (actionVal == 1) logError(i18n.categoryCheckFail.replace('$1', pageToCat) + d.error.code); else logError(i18n.failedToGetContents.replace('$1', pageToCat) + d.error.code); }       }).fail(function { if (actionVal == 1) logError(i18n.categoryCheckFail.replace('$1', pageToCat)); else logError(i18n.failedToGetContents.replace('$1', pageToCat)); });       setTimeout(init, delay);    } });